6 # This script checks for required updates to the database.
8 # Part of the Koha Library Software www.koha.org
9 # Licensed under the GPL.
12 # - Would also be a good idea to offer to do a backup at this time...
14 # NOTE: If you do something more than once in here, make it table driven.
24 use MARC::File::XML ( BinaryEncoding => 'utf8' );
26 # FIXME - The user might be installing a new database, so can't rely
27 # on /etc/koha.conf anyway.
34 %existingtables, # tables already in database
38 $type, $null, $key, $default, $extra,
39 $prefitem, # preference item in systempreferences table
46 my $dbh = C4::Context->dbh;
47 print "connected to your DB. Checking & modifying it\n" unless $silent;
48 $|=1; # flushes output
53 # Tables to add if they don't exist
55 categorytable => "(categorycode char(5) NOT NULL default '',
56 description text default '',
57 itemtypecodes text default '',
58 PRIMARY KEY (categorycode)
60 subcategorytable => "(subcategorycode char(5) NOT NULL default '',
61 description text default '',
62 itemtypecodes text default '',
63 PRIMARY KEY (subcategorycode)
65 mediatypetable => "(mediatypecode char(5) NOT NULL default '',
66 description text default '',
67 itemtypecodes text default '',
68 PRIMARY KEY (mediatypecode)
71 `timestamp` TIMESTAMP NOT NULL ,
72 `user` INT( 11 ) NOT NULL ,
73 `module` TEXT default '',
74 `action` TEXT default '' ,
75 `object` INT(11) NULL ,
76 `info` TEXT default '' ,
77 PRIMARY KEY ( `timestamp` , `user` )
80 module varchar(20) NOT NULL default '',
81 code varchar(20) NOT NULL default '',
82 name varchar(100) NOT NULL default '',
83 title varchar(200) NOT NULL default '',
85 PRIMARY KEY (module,code)
88 alertid int(11) NOT NULL auto_increment,
89 borrowernumber int(11) NOT NULL default '0',
90 type varchar(10) NOT NULL default '',
91 externalid varchar(20) NOT NULL default '',
92 PRIMARY KEY (alertid),
93 KEY borrowernumber (borrowernumber),
94 KEY type (type,externalid)
97 `idnew` int(10) unsigned NOT NULL auto_increment,
98 `title` varchar(250) NOT NULL default '',
100 `lang` varchar(4) NOT NULL default '',
101 `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
102 PRIMARY KEY (`idnew`)
104 repeatable_holidays => "(
105 `id` int(11) NOT NULL auto_increment,
106 `branchcode` varchar(4) NOT NULL default '',
107 `weekday` smallint(6) default NULL,
108 `day` smallint(6) default NULL,
109 `month` smallint(6) default NULL,
110 `title` varchar(50) NOT NULL default '',
111 `description` text NOT NULL,
114 special_holidays => "(
115 `id` int(11) NOT NULL auto_increment,
116 `branchcode` varchar(4) NOT NULL default '',
117 `day` smallint(6) NOT NULL default '0',
118 `month` smallint(6) NOT NULL default '0',
119 `year` smallint(6) NOT NULL default '0',
120 `isexception` smallint(1) NOT NULL default '1',
121 `title` varchar(50) NOT NULL default '',
122 `description` text NOT NULL,
125 overduerules =>"(`branchcode` varchar(255) NOT NULL default '',
126 `categorycode` char(2) NOT NULL default '',
127 `delay1` int(4) default '0',
128 `letter1` varchar(20) default NULL,
129 `debarred1` char(1) default '0',
130 `delay2` int(4) default '0',
131 `debarred2` char(1) default '0',
132 `letter2` varchar(20) default NULL,
133 `delay3` int(4) default '0',
134 `letter3` varchar(20) default NULL,
135 `debarred3` int(1) default '0',
136 PRIMARY KEY (`branchcode`,`categorycode`)
138 cities => "(`cityid` int auto_increment,
139 `city_name` char(100) NOT NULL,
140 `city_zipcode` char(20),
141 PRIMARY KEY (`cityid`)
143 roadtype => "(`roadtypeid` int auto_increment,
144 `road_type` char(100) NOT NULL,
145 PRIMARY KEY (`roadtypeid`)
149 labelid int(11) NOT NULL auto_increment,
150 itemnumber varchar(100) NOT NULL default '',
151 timestamp timestamp(14) NOT NULL,
152 PRIMARY KEY (labelid)
156 id int(4) NOT NULL auto_increment,
157 barcodetype char(100) default '',
158 title tinyint(1) default '0',
159 isbn tinyint(1) default '0',
160 itemtype tinyint(1) default '0',
161 barcode tinyint(1) default '0',
162 dewey tinyint(1) default '0',
163 class tinyint(1) default '0',
164 author tinyint(1) default '0',
165 papertype char(100) default '',
166 startrow int(2) default NULL,
170 reviewid integer NOT NULL auto_increment,
171 borrowernumber integer,
172 biblionumber integer,
175 datereviewed datetime,
176 PRIMARY KEY (reviewid)
178 borrowers_to_borrowers => "(
182 subscriptionroutinglist=>"(
183 routingid integer NOT NULL auto_increment,
184 borrowernumber integer,
186 subscriptionid integer,
187 PRIMARY KEY (routingid)
191 notify_id int(11) NOT NULL default '0',
192 `borrowernumber` int(11) NOT NULL default '0',
193 `itemnumber` int(11) NOT NULL default '0',
194 `notify_date` date NOT NULL default '0000-00-00',
195 `notify_send_date` date default NULL,
196 `notify_level` int(1) NOT NULL default '0',
197 `method` varchar(20) NOT NULL default ''
201 `charge_id` varchar(5) NOT NULL default '',
202 `description` text NOT NULL,
203 `amount` decimal(28,6) NOT NULL default '0.000000',
204 `min` int(4) NOT NULL default '0',
205 `max` int(4) NOT NULL default '0',
206 `level` int(1) NOT NULL default '0',
207 PRIMARY KEY (`charge_id`)
210 `entry` varchar(255) NOT NULL default '',
211 `weight` bigint(20) NOT NULL default '0',
212 PRIMARY KEY (`entry`)
216 `id` int NOT NULL auto_increment,
217 `biblio_auth_number` int NOT NULL,
218 `operation` char(20) NOT NULL,
219 `server` char(20) NOT NULL ,
221 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1",
225 my %requirefields = (
226 subscription => { 'letter' => 'char(20) NULL', 'distributedto' => 'text NULL', 'firstacquidate'=>'date NOT NULL','irregularity'=>'TEXT NULL default \'\'','numberpattern'=>'TINYINT(3) NULL default 0', 'callnumber'=>'text NULL', 'hemisphere' =>'TINYINT(3) NULL default 0', 'issuesatonce'=>'TINYINT(3) NOT NULL default 1', 'branchcode' =>'varchar(12) NOT NULL default \'\'', 'manualhistory'=>'TINYINT(1) NOT NULL default 0','internalnotes'=>'LONGTEXT NULL default \'\''},
227 itemtypes => { 'imageurl' => 'char(200) NULL'},
228 aqbookfund => { 'branchcode' => 'varchar(4) NULL'},
229 aqbudget => { 'branchcode' => 'varchar(4) NULL'},
230 auth_header => { 'marc' => 'BLOB NOT NULL', 'linkid' => 'BIGINT(20) NULL'},
231 auth_subfield_structure =>{ 'hidden' => 'TINYINT(3) NOT NULL default 0', 'kohafield' => 'VARCHAR(45) NOT NULL', 'linkid' => 'TINYINT(1) NOT NULL default 0', 'isurl' => 'TINYINT(1)', 'frameworkcode'=>'VARCHAR(8) NOT NULL'},
232 marc_breeding => { 'isbn' => 'varchar(13) NOT NULL'},
233 serial =>{ 'publisheddate' => 'date', 'claimdate' => 'date', 'itemnumber'=>'text NULL','routingnotes'=>'text NULL',},
234 statistics => { 'associatedborrower' => 'integer'},
235 z3950servers =>{ "name" =>"text", "description" => "text NOT NULL",
236 "position" =>"enum('primary','secondary','') NOT NULL default 'primary'", "icon" =>"text",
237 "type" =>"enum('zed','opensearch') NOT NULL default 'zed'",
239 issues =>{ 'issuedate'=>"date NOT NULL default '0000-00-00'", },
241 # tablename => { 'field' => 'fieldtype' },
244 # Enter here the table to delete.
245 my @TableToDelete = qw(
252 my %uselessfields = (
253 # tablename => "field1,field2",
254 borrowers => "suburb,altstreetaddress,altsuburb,altcity,studentnumber,school,area,preferredcont,altcp",
255 deletedborrowers=> "suburb,altstreetaddress,altsuburb,altcity,studentnumber,school,area,preferredcont,altcp",
257 # the other hash contains other actions that can't be done elsewhere. they are done
258 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
260 # The tabledata hash contains data that should be in the tables.
261 # The uniquefieldrequired hash entry is used to determine which (if any) fields
262 # must not exist in the table for this row to be inserted. If the
263 # uniquefieldrequired entry is already in the table, the existing data is not
264 # modified, unless the forceupdate hash entry is also set. Fields in the
265 # anonymous "forceupdate" hash will be forced to be updated to the default
266 # values given in the %tabledata hash.
270 # { uniquefielrequired => 'fieldname', # the primary key in the table
271 # fieldname => fieldvalue,
272 # fieldname2 => fieldvalue2,
275 systempreferences => [
277 uniquefieldrequired => 'variable',
278 variable => 'useDaysMode',
280 forceupdate => { 'explanation' => 1,
282 explanation => 'How to calculate return dates : Calendar means holidays will be controled, Days means the return date don\'t depend on holidays',
284 options => 'Calendar|Days'
287 uniquefieldrequired => 'variable',
288 variable => 'BorrowersTitles',
289 value => 'Mr|Mrs|Miss|Ms',
290 forceupdate => { 'explanation' => 1,
292 explanation => 'List all Titles for borrowers',
296 uniquefieldrequired => 'variable',
297 variable => 'BorrowerMandatoryField',
298 value => 'cardnumber|surname|address',
299 forceupdate => { 'explanation' => 1,
301 explanation => 'List all mandatory fields for borrowers',
305 uniquefieldrequired => 'variable',
306 variable => 'borrowerRelationship',
307 value => 'father|mother,grand-mother',
308 forceupdate => { 'explanation' => 1,
310 explanation => 'The relationships between a guarantor & a guarantee (separated by | or ,)',
314 uniquefieldrequired => 'variable',
315 variable => 'ReservesMaxPickUpDelay',
317 forceupdate => { 'explanation' => 1,
319 explanation => 'Maximum delay to pick up a reserved document',
323 uniquefieldrequired => 'variable',
324 variable => 'TransfersMaxDaysWarning',
326 forceupdate => { 'explanation' => 1,
328 explanation => 'Max delay before considering the transfer has potentialy a problem',
332 uniquefieldrequired => 'variable',
333 variable => 'memberofinstitution',
335 forceupdate => { 'explanation' => 1,
337 explanation => 'Are your patrons members of institutions',
341 uniquefieldrequired => 'variable',
342 variable => 'ReadingHistory',
344 forceupdate => { 'explanation' => 1,
346 explanation => 'Allow reading record info retrievable from issues and oldissues tables',
350 uniquefieldrequired => 'variable',
351 variable => 'IssuingInProcess',
353 forceupdate => { 'explanation' => 1,
355 explanation => 'Allow no debt alert if the patron is issuing item that accumulate debt',
359 uniquefieldrequired => 'variable',
360 variable => 'AutomaticItemReturn',
362 forceupdate => { 'explanation' => 1,
364 explanation => 'This Variable allow or not to return automaticly to his homebranch',
368 uniquefieldrequired => 'variable',
369 variable => 'reviewson',
371 forceupdate => { 'explanation' => 1,
373 explanation => 'Allows patrons to submit reviews from the opac',
377 uniquefieldrequired => 'variable',
378 variable => 'intranet_includes',
380 forceupdate => { 'explanation' => 1,
382 explanation => 'The includes directory you want for specific look of Koha (includes or includes_npl for example)',
386 uniquefieldrequired => 'variable',
387 variable => 'AutoLocation',
389 forceupdate => { 'explanation' => 1,
391 explanation => 'switch to activate or not Autolocation, if Yes, the Librarian can\'t change his location, it\'s defined by branchip',
395 uniquefieldrequired => 'variable',
396 variable => 'serialsadditems',
402 explanation => 'If set, a new item will be automatically added when receiving an issue',
406 uniquefieldrequired => 'variable',
407 variable => 'expandedSearchOption',
413 explanation => 'search among marc field',
417 uniquefieldrequired => 'variable',
418 variable => 'RequestOnOpac',
420 forceupdate => { 'explanation' => 1,
422 explanation => 'option to allow reserves on opac',
426 uniquefieldrequired => 'variable',
427 variable => 'OpacCloud',
429 forceupdate => { 'explanation' => 1,
431 explanation => 'Enable / Disable cloud link on OPAC (Require to run misc/cronjobs/build_browser_and_cloud.pl on the server)',
435 uniquefieldrequired => 'variable',
436 variable => 'OpacBrowser',
438 forceupdate => { 'explanation' => 1,
440 explanation => 'Enable/Disable browser link on OPAC (Require to run misc/cronjobs/build_browser_and_cloud.pl on the server)',
444 uniquefieldrequired => 'variable',
445 variable => 'OpacTopissue',
447 forceupdate => { 'explanation' => 1,
449 explanation => 'Enable / Disable the top issue link on OPAC',
453 uniquefieldrequired => 'variable',
454 variable => 'OpacAuthorities',
456 forceupdate => { 'explanation' => 1,
458 explanation => 'Enable / Disable the search authority link on OPAC',
462 uniquefieldrequired => 'variable',
463 variable => 'CataloguingLog',
465 forceupdate => {'explanation' => 1, 'type' => 1},
466 explanation => 'Active this if you want to log cataloguing action.',
470 uniquefieldrequired => 'variable',
471 variable => 'BorrowersLog',
473 forceupdate => {'explanation' => 1, 'type' => 1},
474 explanation => 'Active this if you want to log borrowers edition/creation/deletion...',
478 uniquefieldrequired => 'variable',
479 variable => 'SubscriptionLog',
481 forceupdate => {'explanation' => 1, 'type' => 1},
482 explanation => 'Active this if you want to log Subscription action',
486 uniquefieldrequired => 'variable',
487 variable => 'IssueLog',
489 forceupdate => {'explanation' => 1, 'type' => 1},
490 explanation => 'Active this if you want to log issue.',
494 uniquefieldrequired => 'variable',
495 variable => 'ReturnLog',
497 forceupdate => {'explanation' => 1, 'type' => 1},
498 explanation => 'Active this if you want to log the circulation return',
502 uniquefieldrequired => 'variable',
503 variable => 'Version',
505 forceupdate => {'explanation' => 1, 'type' => 1},
506 explanation => 'Koha Version',
510 uniquefieldrequired => 'variable',
511 variable => 'LetterLog',
513 forceupdate => {'explanation' => 1, 'type' => 1},
514 explanation => 'Active this if you want to log all the letter sent',
518 uniquefieldrequired => 'variable',
519 variable => 'FinesLog',
521 forceupdate => {'explanation' => 1, 'type' => 1},
522 explanation => 'Active this if you want to log fines',
526 uniquefieldrequired => 'variable',
527 variable => 'NoZebra',
529 forceupdate => {'explanation' => 1, 'type' => 1},
530 explanation => 'Active this if you want NOT to use zebra (large libraries should avoid this parameters)',
534 uniquefieldrequired => 'variable',
535 variable => 'NoZebraIndexes',
537 forceupdate => {'explanation' => 1, 'type' => 1},
538 explanation => "Enter a specific hash for NoZebra indexes. Enter : 'indexname' => '100a,245a,500*','index2' => '...'",
544 uniquefieldrequired => 'bit',
546 flag => 'editauthorities',
547 flagdesc => 'allow to edit authorities',
551 uniquefieldrequired => 'bit',
554 flagdesc => 'allow to manage serials subscriptions',
558 uniquefieldrequired => 'bit',
561 flagdesc => 'allow to access to the reports module',
565 authorised_values => [
567 uniquefieldrequired => 'id',
568 category => 'SUGGEST',
569 authorised_value => 'Not enough budget',
570 lib => 'This book it too much expensive',
575 my %fielddefinitions = (
577 # { field => 'fieldname',
578 # type => 'fieldtype',
586 field => 'booksellerid',
601 extra => 'auto_increment',
604 field => 'listprice',
605 type => 'varchar(10)',
612 field => 'invoiceprice',
613 type => 'varchar(10)',
623 field => 'notify_id',
631 field => 'notify_level',
642 { field => 'firstname',
646 { field => 'initials',
650 { field => 'B_email',
653 after => 'B_zipcode',
656 field => 'streetnumber', # street number (hidden if streettable table is empty)
662 field => 'streettype', # street table, list builded from a system table
665 after => 'streetnumber',
672 field => 'B_streetnumber', # street number (hidden if streettable table is empty)
678 field => 'B_streettype', # street table, list builded from a system table
681 after => 'B_streetnumber',
690 field => 'address2', # complement address
702 field => 'contactfirstname', # contact's firstname
705 after => 'contactname',
708 field => 'contacttitle', # contact's title
711 after => 'contactfirstname',
714 field => 'branchcode',
715 type => 'varchar(10)',
721 field => 'categorycode',
722 type => 'varchar(10)',
732 type => 'varchar(25)',
740 type => 'varchar(4)',
748 type => 'varchar(30)',
754 deletedbiblioitems => [
757 type => 'varchar(30)',
766 type => 'varchar(15)',
773 field => 'branchprinter',
774 type => 'varchar(100)',
781 field => 'branchcode',
782 type => 'varchar(10)',
790 field => 'frombranch',
791 type => 'VARCHAR(10)',
799 type => 'VARCHAR(10)',
808 field => 'category_type',
816 field => 'categorycode',
817 type => 'varchar(10)',
825 deletedborrowers => [
826 { field => 'firstname',
830 { field => 'initials',
834 { field => 'B_email',
837 after => 'B_zipcode',
840 field => 'streetnumber', # street number (hidden if streettable table is empty)
846 field => 'streettype', # street table, list builded from a system table
849 after => 'streetnumber',
856 field => 'B_streetnumber', # street number (hidden if streettable table is empty)
862 field => 'B_streettype', # street table, list builded from a system table
865 after => 'B_streetnumber',
874 field => 'address2', # complement address
886 field => 'contactfirstname', # contact's firstname
889 after => 'contactname',
892 field => 'contacttitle', # contact's title
895 after => 'contactfirstname',
901 field => 'borrowernumber',
903 null => 'NULL', # can be null when a borrower is deleted and the foreign key rule executed
909 field => 'itemnumber',
911 null => 'NULL', # can be null when a borrower is deleted and the foreign key rule executed
917 field => 'branchcode',
918 type => 'varchar(10)',
925 field => 'issuedate',
929 default => '0000-00-00',
940 default => '0000-00-00',
944 field => 'cutterextra',
945 type => 'varchar(45)',
952 field => 'issue_date',
960 field => 'homebranch',
961 type => 'varchar(10)',
968 field => 'holdingbranch',
969 type => 'varchar(10)',
977 type => 'varchar(10)',
987 type => 'varchar(10)',
1010 marc_subfield_structure => [
1012 field => 'defaultvalue',
1021 field => 'expirationdate',
1038 field => 'waitingdate',
1058 field => 'dateadded',
1059 type => 'timestamp',
1063 systempreferences => [
1073 field => 'explanation',
1095 # { indexname => 'index detail'
1099 { indexname => 'PRIMARY',
1105 { indexname => 'booksellerid',
1106 content => 'booksellerid',
1110 { indexname => 'basketno',
1111 content => 'basketno',
1114 aqorderbreakdown => [
1115 { indexname => 'ordernumber',
1116 content => 'ordernumber',
1118 { indexname => 'bookfundid',
1119 content => 'bookfundid',
1123 { indexname => 'isbn',
1126 { indexname => 'publishercode',
1127 content => 'publishercode',
1132 indexname => 'branchcode',
1133 content => 'branchcode',
1137 branchrelations => [
1139 indexname => 'PRIMARY',
1140 content => 'categorycode',
1144 branchrelations => [
1145 { indexname => 'PRIMARY',
1146 content => 'branchcode,categorycode',
1149 { indexname => 'branchcode',
1150 content => 'branchcode',
1152 { indexname => 'categorycode',
1153 content => 'categorycode',
1157 { indexname => 'PRIMARY',
1158 content => 'currency',
1164 indexname => 'categorycode',
1165 content => 'categorycode',
1169 { indexname => 'homebranch',
1170 content => 'homebranch',
1172 { indexname => 'holdingbranch',
1173 content => 'holdingbranch',
1178 indexname => 'itemtype',
1179 content => 'itemtype',
1183 { indexname => 'shelfnumber',
1184 content => 'shelfnumber',
1186 { indexname => 'itemnumber',
1187 content => 'itemnumber',
1191 { indexname => 'PRIMARY',
1198 my %foreign_keys = (
1200 # { key => 'the key in table' (must be indexed)
1201 # foreigntable => 'the foreigntable name', # (the parent)
1202 # foreignkey => 'the foreign key column(s)' # (in the parent)
1203 # onUpdate => 'CASCADE|SET NULL|NO ACTION| RESTRICT',
1204 # onDelete => 'CASCADE|SET NULL|NO ACTION| RESTRICT',
1207 branchrelations => [
1208 { key => 'branchcode',
1209 foreigntable => 'branches',
1210 foreignkey => 'branchcode',
1211 onUpdate => 'CASCADE',
1212 onDelete => 'CASCADE',
1214 { key => 'categorycode',
1215 foreigntable => 'branchcategories',
1216 foreignkey => 'categorycode',
1217 onUpdate => 'CASCADE',
1218 onDelete => 'CASCADE',
1222 { key => 'shelfnumber',
1223 foreigntable => 'bookshelf',
1224 foreignkey => 'shelfnumber',
1225 onUpdate => 'CASCADE',
1226 onDelete => 'CASCADE',
1228 { key => 'itemnumber',
1229 foreigntable => 'items',
1230 foreignkey => 'itemnumber',
1231 onUpdate => 'CASCADE',
1232 onDelete => 'CASCADE',
1235 # onDelete is RESTRICT on reference tables (branches, itemtype) as we don't want items to be
1236 # easily deleted, but branches/itemtype not too easy to empty...
1238 { key => 'biblionumber',
1239 foreigntable => 'biblio',
1240 foreignkey => 'biblionumber',
1241 onUpdate => 'CASCADE',
1242 onDelete => 'CASCADE',
1244 { key => 'itemtype',
1245 foreigntable => 'itemtypes',
1246 foreignkey => 'itemtype',
1247 onUpdate => 'CASCADE',
1248 onDelete => 'RESTRICT',
1252 { key => 'biblioitemnumber',
1253 foreigntable => 'biblioitems',
1254 foreignkey => 'biblioitemnumber',
1255 onUpdate => 'CASCADE',
1256 onDelete => 'CASCADE',
1258 { key => 'homebranch',
1259 foreigntable => 'branches',
1260 foreignkey => 'branchcode',
1261 onUpdate => 'CASCADE',
1262 onDelete => 'RESTRICT',
1264 { key => 'holdingbranch',
1265 foreigntable => 'branches',
1266 foreignkey => 'branchcode',
1267 onUpdate => 'CASCADE',
1268 onDelete => 'RESTRICT',
1272 { key => 'booksellerid',
1273 foreigntable => 'aqbooksellers',
1275 onUpdate => 'CASCADE',
1276 onDelete => 'RESTRICT',
1280 { key => 'basketno',
1281 foreigntable => 'aqbasket',
1282 foreignkey => 'basketno',
1283 onUpdate => 'CASCADE',
1284 onDelete => 'CASCADE',
1286 { key => 'biblionumber',
1287 foreigntable => 'biblio',
1288 foreignkey => 'biblionumber',
1289 onUpdate => 'SET NULL',
1290 onDelete => 'SET NULL',
1294 { key => 'listprice',
1295 foreigntable => 'currency',
1296 foreignkey => 'currency',
1297 onUpdate => 'CASCADE',
1298 onDelete => 'CASCADE',
1300 { key => 'invoiceprice',
1301 foreigntable => 'currency',
1302 foreignkey => 'currency',
1303 onUpdate => 'CASCADE',
1304 onDelete => 'CASCADE',
1307 aqorderbreakdown => [
1308 { key => 'ordernumber',
1309 foreigntable => 'aqorders',
1310 foreignkey => 'ordernumber',
1311 onUpdate => 'CASCADE',
1312 onDelete => 'CASCADE',
1314 { key => 'bookfundid',
1315 foreigntable => 'aqbookfund',
1316 foreignkey => 'bookfundid',
1317 onUpdate => 'CASCADE',
1318 onDelete => 'CASCADE',
1321 branchtransfers => [
1322 { key => 'frombranch',
1323 foreigntable => 'branches',
1324 foreignkey => 'branchcode',
1325 onUpdate => 'CASCADE',
1326 onDelete => 'CASCADE',
1328 { key => 'tobranch',
1329 foreigntable => 'branches',
1330 foreignkey => 'branchcode',
1331 onUpdate => 'CASCADE',
1332 onDelete => 'CASCADE',
1334 { key => 'itemnumber',
1335 foreigntable => 'items',
1336 foreignkey => 'itemnumber',
1337 onUpdate => 'CASCADE',
1338 onDelete => 'CASCADE',
1342 { key => 'categorycode',
1343 foreigntable => 'categories',
1344 foreignkey => 'categorycode',
1345 onUpdate => 'CASCADE',
1346 onDelete => 'CASCADE',
1348 { key => 'itemtype',
1349 foreigntable => 'itemtypes',
1350 foreignkey => 'itemtype',
1351 onUpdate => 'CASCADE',
1352 onDelete => 'CASCADE',
1355 issues => [ # constraint is SET NULL : when a borrower or an item is deleted, we keep the issuing record
1357 { key => 'borrowernumber',
1358 foreigntable => 'borrowers',
1359 foreignkey => 'borrowernumber',
1360 onUpdate => 'SET NULL',
1361 onDelete => 'SET NULL',
1363 { key => 'itemnumber',
1364 foreigntable => 'items',
1365 foreignkey => 'itemnumber',
1366 onUpdate => 'SET NULL',
1367 onDelete => 'SET NULL',
1371 { key => 'borrowernumber',
1372 foreigntable => 'borrowers',
1373 foreignkey => 'borrowernumber',
1374 onUpdate => 'CASCADE',
1375 onDelete => 'CASCADE',
1377 { key => 'biblionumber',
1378 foreigntable => 'biblio',
1379 foreignkey => 'biblionumber',
1380 onUpdate => 'CASCADE',
1381 onDelete => 'CASCADE',
1383 { key => 'itemnumber',
1384 foreigntable => 'items',
1385 foreignkey => 'itemnumber',
1386 onUpdate => 'CASCADE',
1387 onDelete => 'CASCADE',
1389 { key => 'branchcode',
1390 foreigntable => 'branches',
1391 foreignkey => 'branchcode',
1392 onUpdate => 'CASCADE',
1393 onDelete => 'CASCADE',
1396 borrowers => [ # foreign keys are RESTRICT as we don't want to delete borrowers when a branch is deleted
1397 # but prevent deleting a branch as soon as it has 1 borrower !
1398 { key => 'categorycode',
1399 foreigntable => 'categories',
1400 foreignkey => 'categorycode',
1401 onUpdate => 'RESTRICT',
1402 onDelete => 'RESTRICT',
1404 { key => 'branchcode',
1405 foreigntable => 'branches',
1406 foreignkey => 'branchcode',
1407 onUpdate => 'RESTRICT',
1408 onDelete => 'RESTRICT',
1411 deletedborrowers => [ # foreign keys are RESTRICT as we don't want to delete borrowers when a branch is deleted
1412 # but prevent deleting a branch as soon as it has 1 borrower !
1413 { key => 'categorycode',
1414 foreigntable => 'categories',
1415 foreignkey => 'categorycode',
1416 onUpdate => 'RESTRICT',
1417 onDelete => 'RESTRICT',
1419 { key => 'branchcode',
1420 foreigntable => 'branches',
1421 foreignkey => 'branchcode',
1422 onUpdate => 'RESTRICT',
1423 onDelete => 'RESTRICT',
1427 { key => 'borrowernumber',
1428 foreigntable => 'borrowers',
1429 foreignkey => 'borrowernumber',
1430 onUpdate => 'CASCADE',
1431 onDelete => 'CASCADE',
1433 { key => 'itemnumber',
1434 foreigntable => 'items',
1435 foreignkey => 'itemnumber',
1436 onUpdate => 'SET NULL',
1437 onDelete => 'SET NULL',
1440 auth_tag_structure => [
1441 { key => 'authtypecode',
1442 foreigntable => 'auth_types',
1443 foreignkey => 'authtypecode',
1444 onUpdate => 'CASCADE',
1445 onDelete => 'CASCADE',
1448 # FIXME : don't constraint auth_*_table and auth_word, as they may be replaced by zebra
1453 my %column_change = (
1457 from => 'emailaddress',
1462 from => 'streetaddress',
1464 after => 'initials',
1467 from => 'faxnumber',
1472 from => 'textmessaging',
1478 to => 'contactnote',
1479 after => 'opacnote',
1482 from => 'physstreet',
1487 from => 'streetcity',
1489 after => 'B_address',
1502 from => 'homezipcode',
1509 after => 'B_zipcode',
1514 after => 'dateenrolled',
1517 from => 'guarantor',
1518 to => 'guarantorid',
1519 after => 'contactname',
1522 from => 'altrelationship',
1523 to => 'relationship',
1524 after => 'borrowernotes',
1528 deletedborrowers => [
1530 from => 'emailaddress',
1535 from => 'streetaddress',
1537 after => 'initials',
1540 from => 'faxnumber',
1545 from => 'textmessaging',
1551 to => 'contactnote',
1552 after => 'opacnote',
1555 from => 'physstreet',
1560 from => 'streetcity',
1562 after => 'B_address',
1575 from => 'homezipcode',
1582 after => 'B_zipcode',
1587 after => 'dateenrolled',
1590 from => 'guarantor',
1591 to => 'guarantorid',
1592 after => 'contactname',
1595 from => 'altrelationship',
1596 to => 'relationship',
1597 after => 'borrowernotes',
1603 # MOVE all tables TO UTF-8 and innoDB
1604 $sth = $dbh->prepare("show table status");
1606 while ( my $table = $sth->fetchrow_hashref ) {
1607 next if $table->{Name} eq 'marc_word';
1608 next if $table->{Name} eq 'marc_subfield_table';
1609 next if $table->{Name} eq 'auth_word';
1610 next if $table->{Name} eq 'auth_subfield_table';
1611 if ($table->{Engine} ne 'InnoDB') {
1612 $dbh->do("ALTER TABLE $table->{Name} TYPE = innodb");
1613 print "moving $table->{Name} to InnoDB\n";
1615 unless ($table->{Collation} =~ /^utf8/) {
1616 print "moving $table->{Name} to utf8\n";
1617 $dbh->do("ALTER TABLE $table->{Name} CONVERT TO CHARACTER SET utf8");
1618 $dbh->do("ALTER TABLE $table->{Name} DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
1619 # FIXME : maybe a ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8 would be better, def char set seems to work fine. If any problem encountered, let's try with convert !
1625 foreach my $table (keys %column_change) {
1626 $sth = $dbh->prepare("show columns from $table");
1629 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1631 $types{$column}->{type} ="$type";
1632 $types{$column}->{null} = "$null";
1633 $types{$column}->{key} = "$key";
1634 $types{$column}->{default} = "$default";
1635 $types{$column}->{extra} = "$extra";
1637 my $tablerows = $column_change{$table};
1638 foreach my $row ( @$tablerows ) {
1639 if ($types{$row->{from}}->{type}) {
1640 print "altering $table $row->{from} to $row->{to}\n";
1641 # ALTER TABLE `borrowers` CHANGE `faxnumber` `fax` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
1642 # alter table `borrowers` change `faxnumber` `fax` type text null after phone
1644 "alter table `$table` change `$row->{from}` `$row->{to}` $types{$row->{from}}->{type} ".
1645 ($types{$row->{from}}->{null} eq 'YES'?" NULL":" NOT NULL").
1646 ($types{$row->{from}}->{default}?" default ".$types{$row->{from}}->{default}:"").
1647 "$types{$row->{from}}->{extra} after $row->{after} ";
1654 # Enter here the field you want to delete from DB.
1655 # FIXME :: there is a %uselessfield before which seems doing the same things.
1656 my %fieldtodelete = (
1657 # tablename => [fieldname1,fieldname2,...]
1661 print "removing some unused fields...\n";
1662 foreach my $table ( keys %fieldtodelete ) {
1663 foreach my $field ( @{$fieldtodelete{$table}} ){
1664 print "removing ".$field." from ".$table;
1665 my $sth = $dbh->prepare("ALTER TABLE $table DROP $field");
1668 print "Error : $sth->errstr \n";
1673 # Enter here the line you want to remove from DB.
1674 my %linetodelete = (
1675 # table name => where clause.
1676 userflags => "bit = 8", # delete the 'reserveforself' flags
1680 #-------------------
1685 # Get version of MySQL database engine.
1686 my $mysqlversion = `mysqld --version`;
1687 $mysqlversion =~ /Ver (\S*) /;
1689 if ( $mysqlversion ge '3.23' ) {
1690 print "Could convert to MyISAM database tables...\n" unless $silent;
1693 #---------------------------------
1696 # Collect all tables into a list
1697 $sth = $dbh->prepare("show tables");
1699 while ( my ($table) = $sth->fetchrow ) {
1700 $existingtables{$table} = 1;
1704 # Now add any missing tables
1705 foreach $table ( keys %requiretables ) {
1706 unless ( $existingtables{$table} ) {
1707 print "Adding $table table...\n" unless $silent;
1708 my $sth = $dbh->prepare("create table $table $requiretables{$table}");
1711 print "Error : $sth->errstr \n";
1717 #---------------------------------
1720 foreach $table ( keys %requirefields ) {
1721 print "Check table $table\n" if $debug and not $silent;
1722 $sth = $dbh->prepare("show columns from $table");
1725 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1727 $types{$column} = $type;
1729 foreach $column ( keys %{ $requirefields{$table} } ) {
1730 print " Check column $column [$types{$column}]\n" if $debug and not $silent;
1731 if ( !$types{$column} ) {
1733 # column doesn't exist
1734 print "Adding $column field to $table table...\n" unless $silent;
1735 $query = "alter table $table
1736 add column $column " . $requirefields{$table}->{$column};
1737 print "Execute: $query\n" if $debug;
1738 my $sti = $dbh->prepare($query);
1741 print "**Error : $sti->errstr \n";
1748 foreach $table ( keys %fielddefinitions ) {
1749 print "Check table $table\n" if $debug;
1750 $sth = $dbh->prepare("show columns from $table");
1753 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1755 $definitions->{$column}->{type} = $type;
1756 $definitions->{$column}->{null} = $null;
1757 $definitions->{$column}->{null} = 'NULL' if $null eq 'YES';
1758 $definitions->{$column}->{key} = $key;
1759 $definitions->{$column}->{default} = $default;
1760 $definitions->{$column}->{extra} = $extra;
1762 my $fieldrow = $fielddefinitions{$table};
1763 foreach my $row (@$fieldrow) {
1764 my $field = $row->{field};
1765 my $type = $row->{type};
1766 my $null = $row->{null};
1767 # $null = 'YES' if $row->{null} eq 'NULL';
1768 my $key = $row->{key};
1769 my $default = $row->{default};
1770 # $default="''" unless $default;
1771 my $extra = $row->{extra};
1772 my $def = $definitions->{$field};
1773 my $after = ($row->{after}?" after ".$row->{after}:"");
1775 unless ( $type eq $def->{type}
1776 && $null eq $def->{null}
1777 && $key eq $def->{key}
1778 && $extra eq $def->{extra} )
1780 if ( $null eq '' ) {
1783 if ( $key eq 'PRI' ) {
1784 $key = 'PRIMARY KEY';
1786 unless ( $extra eq 'auto_increment' ) {
1790 # if it's a new column use "add", if it's an old one, use "change".
1792 if ($definitions->{$field}->{type}) {
1793 $action="change $field"
1797 # if it's a primary key, drop the previous pk, before altering the table
1798 print " alter or create $field in $table\n" unless $silent;
1800 if ($key ne 'PRIMARY KEY') {
1801 # warn "alter table $table $action $field $type $null $key $extra default $default $after";
1802 $query = "alter table $table $action $field $type $null $key $extra ".($default?"default ".$dbh->quote($default):"")." $after";
1804 # warn "alter table $table drop primary key, $action $field $type $null $key $extra default $default $after";
1805 # something strange : for indexes UNIQUE, they are reported as primary key here.
1806 # but if you try to run with drop primary key, it fails.
1807 # thus, we run the query twice, one will fail, one will succeed.
1809 $query="alter table $table drop primary key, $action $field $type $null $key $extra ".($default?"default ".$dbh->quote($default):"")." $after";
1810 $query="alter table $table $action $field $type $null $key $extra ".($default?"default ".$dbh->quote($default):"")." $after";
1817 print "removing some unused data...\n";
1818 foreach my $table ( keys %linetodelete ) {
1819 foreach my $where ( @{linetodelete{$table}} ){
1820 print "DELETE FROM ".$table." where ".$where;
1822 my $sth = $dbh->prepare("DELETE FROM $table where $where");
1825 print "Error : $sth->errstr \n";
1830 # Populate tables with required data
1832 # synch table and deletedtable.
1833 foreach my $table (('borrowers','items','biblio','biblioitems')) {
1834 my %deletedborrowers;
1835 print "synch'ing $table and deleted$table\n";
1836 $sth = $dbh->prepare("show columns from deleted$table");
1838 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ) {
1839 $deletedborrowers{$column}=1;
1841 $sth = $dbh->prepare("show columns from $table");
1844 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ) {
1845 unless ($deletedborrowers{$column}) {
1846 my $newcol="alter table deleted$table add $column $type";
1847 if ($null eq 'YES') {
1848 $newcol .= " NULL ";
1850 $newcol .= " NOT NULL ";
1852 $newcol .= "default ".$dbh->quote($default) if $default;
1853 $newcol .= " after $previous" if $previous;
1855 print "creating column $column\n";
1861 # update publisheddate
1863 $sth = $dbh->prepare("select count(*) from serial where publisheddate is NULL");
1865 my ($emptypublished) = $sth->fetchrow;
1866 if ($emptypublished) {
1867 print "Updating publisheddate\n";
1868 $dbh->do("update serial set publisheddate=planneddate where publisheddate is NULL");
1870 foreach my $table ( keys %tabledata ) {
1871 print "Checking for data required in table $table...\n" unless $silent;
1872 my $tablerows = $tabledata{$table};
1873 foreach my $row (@$tablerows) {
1874 my $uniquefieldrequired = $row->{uniquefieldrequired};
1875 my $uniquevalue = $row->{$uniquefieldrequired};
1876 my $forceupdate = $row->{forceupdate};
1879 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
1881 $sth->execute($uniquevalue);
1883 foreach my $field (keys %$forceupdate) {
1884 if ($forceupdate->{$field}) {
1885 my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
1886 $sth->execute($row->{$field}, $uniquevalue);
1890 print "Adding row to $table: " unless $silent;
1894 foreach my $field ( keys %$row ) {
1895 next if $field eq 'uniquefieldrequired';
1896 next if $field eq 'forceupdate';
1897 my $value = $row->{$field};
1898 push @values, $value;
1899 print " $field => $value" unless $silent;
1900 $fieldlist .= "$field,";
1901 $placeholders .= "?,";
1903 print "\n" unless $silent;
1904 $fieldlist =~ s/,$//;
1905 $placeholders =~ s/,$//;
1906 print "insert into $table ($fieldlist) values ($placeholders)";
1909 "insert into $table ($fieldlist) values ($placeholders)");
1910 $sth->execute(@values);
1916 # check indexes and create them when needed
1918 print "Checking for index required...\n" unless $silent;
1919 foreach my $table ( keys %indexes ) {
1921 # read all indexes from $table
1923 $sth = $dbh->prepare("show index from $table");
1925 my %existingindexes;
1926 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow ) {
1927 $existingindexes{$key_name} = 1;
1929 # read indexes to check
1930 my $tablerows = $indexes{$table};
1931 foreach my $row (@$tablerows) {
1932 my $key_name=$row->{indexname};
1933 if ($existingindexes{$key_name} eq 1) {
1934 # print "$key_name existing";
1936 print "\tCreating index $key_name in $table\n";
1938 if ($row->{indexname} eq 'PRIMARY') {
1939 $sql = "alter table $table ADD PRIMARY KEY ($row->{content})";
1941 $sql = "alter table $table ADD INDEX $key_name ($row->{content}) $row->{type}";
1944 print "Error $sql : $dbh->err \n" if $dbh->err;
1950 # check foreign keys and create them when needed
1952 print "Checking for foreign keys required...\n" unless $silent;
1953 foreach my $table ( keys %foreign_keys ) {
1955 # read all indexes from $table
1957 $sth = $dbh->prepare("show table status like '$table'");
1959 my $stat = $sth->fetchrow_hashref;
1960 # read indexes to check
1961 my $tablerows = $foreign_keys{$table};
1962 foreach my $row (@$tablerows) {
1963 my $foreign_table=$row->{foreigntable};
1964 if ($stat->{'Comment'} =~/$foreign_table/) {
1965 # print "$foreign_table existing\n";
1967 print "\tCreating foreign key $foreign_table in $table\n";
1968 # first, drop any orphan value in child table
1969 if ($row->{onDelete} ne "RESTRICT") {
1970 my $sql = "delete from $table where $row->{key} not in (select $row->{foreignkey} from $row->{foreigntable})";
1972 print "SQL ERROR: $sql : $dbh->err \n" if $dbh->err;
1974 my $sql="alter table $table ADD FOREIGN KEY $row->{key} ($row->{key}) REFERENCES $row->{foreigntable} ($row->{foreignkey})";
1975 $sql .= " on update ".$row->{onUpdate} if $row->{onUpdate};
1976 $sql .= " on delete ".$row->{onDelete} if $row->{onDelete};
1979 print "====================
1980 An error occured during :
1982 It probably means there is something wrong in your DB : a row ($table.$row->{key}) refers to a value in $row->{foreigntable}.$row->{foreignkey} that does not exist. solve the problem and run updater again (or just the previous SQL statement).
1983 You can find those values with select
1984 \t$table.* from $table where $row->{key} not in (select $row->{foreignkey} from $row->{foreigntable})
1985 ====================\n
1991 # now drop useless tables
1992 foreach $table ( @TableToDelete ) {
1993 if ( $existingtables{$table} ) {
1994 print "Dropping unused table $table\n" if $debug and not $silent;
1995 $dbh->do("drop table $table");
1997 print "Error : $dbh->errstr \n";
2006 # create frameworkcode row in biblio table & fill it with marc_biblio.frameworkcode.
2009 # 1st, get how many biblio we will have to do...
2010 $sth = $dbh->prepare('select count(*) from marc_biblio');
2012 my ($totaltodo) = $sth->fetchrow;
2014 $sth = $dbh->prepare("show columns from biblio");
2017 my $bibliofwexist=0;
2018 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ){
2019 $bibliofwexist=1 if $column eq 'frameworkcode';
2021 unless ($bibliofwexist) {
2022 print "moving biblioframework to biblio table\n";
2023 $dbh->do('ALTER TABLE `biblio` ADD `frameworkcode` VARCHAR( 4 ) NOT NULL AFTER `biblionumber`');
2024 $sth = $dbh->prepare('select biblionumber,frameworkcode from marc_biblio');
2026 my $sth_update = $dbh->prepare('update biblio set frameworkcode=? where biblionumber=?');
2028 while (my ($biblionumber,$frameworkcode) = $sth->fetchrow) {
2029 $sth_update->execute($frameworkcode,$biblionumber);
2031 print "\r$totaldone / $totaltodo" unless ($totaldone % 100);
2036 # at last, remove useless fields
2037 foreach $table ( keys %uselessfields ) {
2038 my @fields = split /,/,$uselessfields{$table};
2041 foreach my $fieldtodrop (@fields) {
2042 $fieldtodrop =~ s/\t//g;
2043 $fieldtodrop =~ s/\n//g;
2045 $sth = $dbh->prepare("show columns from $table");
2047 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2049 $exists =1 if ($column eq $fieldtodrop);
2052 print "deleting $fieldtodrop field in $table...\n" unless $silent;
2053 my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
2060 # Changing aqbookfund's primary key
2062 $sth=$dbh->prepare("ALTER TABLE `aqbookfund` DROP PRIMARY KEY , ADD PRIMARY KEY ( `bookfundid` , `branchcode` ) ;");
2070 # Revision 1.169 2007/06/26 09:23:26 tipaul
2071 # improving OpacBrowser systempref explanation
2073 # Revision 1.168 2007/06/25 15:02:31 tipaul
2074 # missing field declaration
2076 # Revision 1.167 2007/06/15 13:09:08 toins
2077 # bugfix : bibliotitems.dewey & deletedbiblioitems.dewey mustn't be double(8,6).
2079 # Revision 1.166 2007/06/08 09:40:12 toins
2080 # bug fix : items.homebranch must be VARCHAR(10)
2082 # Revision 1.165 2007/05/23 16:33:10 tipaul
2083 # skip move to innoDB for the 4 22 tables, that are used to store MARC records, are useless in Koha 3.0 The process is very very long, so the updatedatabase should speed up a lot (by long I mean 1 hour on my Dual core with SCSI disk, for a 50 000 biblios long table
2085 # Revision 1.164 2007/05/04 16:24:09 tipaul
2086 # various bugfixes on parameters modules + adding default NoZebraIndexes systempreference if it's empty
2088 # Revision 1.163 2007/05/02 16:44:31 tipaul
2089 # NoZebra SQL index management :
2090 # * adding 3 subs in Biblio.pm
2091 # - GetNoZebraIndexes, that get the index structure in a new systempreference (added with this commit)
2092 # - _DelBiblioNoZebra, that retrieve all index entries for a biblio and remove in a variable the biblio reference
2093 # - _AddBiblioNoZebra, that add index entries for a biblio.
2094 # Note that the 2 _Add and _Del subs work only in a hash variable, to speed up things in case of a modif (ie : delete+add). The effective SQL update is done in the ModZebra sub (that existed before, and dealed with zebra index).
2095 # I think the code has to be more deeply tested, but it works at least partially.
2097 # Revision 1.162 2007/04/30 16:16:50 tipaul
2098 # bugfix for updatedatabase : when there is no default value (NULL fields) + removing bibliothesaurus table+adding NoZebra systempref (False by default)
2100 # Revision 1.161 2007/04/13 16:27:55 hdl
2101 # Adding Version variable to systempreferences.
2103 # Revision 1.160 2007/03/19 18:35:13 toins
2104 # - adding default value in marc_subfield_structure.
2105 # - now marc_subfields_structure displays subfields in tab view.
2107 # Revision 1.159 2007/03/16 01:25:09 kados
2108 # Using my precrash CVS copy I did the following:
2110 # cvs -z3 -d:ext:kados@cvs.savannah.nongnu.org:/sources/koha co -P koha
2111 # find koha.precrash -type d -name "CVS" -exec rm -v {} \;
2112 # cp -r koha.precrash/* koha/
2116 # This should in theory put us right back where we were before the crash
2118 # Revision 1.159 2007/03/12 17:52:30 rych
2119 # add pri key to userflags
2121 # Revision 1.158 2007/03/09 15:14:57 tipaul
2122 # rel_3_0 moved to HEAD
2124 # Revision 1.157.2.56 2007/01/31 16:22:54 btoumi
2125 # -add possibility to use isbn with length of 13 characters
2126 # for Import datas in the reservoir.
2127 # -modify isbn field in marc_breeding table (varchar 13)
2128 # -add isbn filter (no - )when u read a notice from reservoir
2129 # -add filter to have right field 100
2131 # Revision 1.157.2.55 2007/01/30 10:50:19 tipaul
2132 # adding 2 usefull indexes to biblioitems table
2134 # Revision 1.157.2.54 2007/01/29 16:45:52 toins
2135 # * adding a new default authorised value : SUGGEST.
2136 # SUGGEST give some reasons to accept or reject a suggestion.
2138 # * default value for borrowersMandatoryfield syspref is now "cardnumber|surname|adress"
2140 # Revision 1.157.2.53 2007/01/26 20:48:37 hdl
2141 # Serials management : Bugfixes + improvements.
2142 # - Partial dates are now managed
2143 # - next Date Calculation with irregularity tested for 1 week and 1 month.
2144 # - manage if subscription is abouttoexpire or expired.
2145 # - Adding some information on serials pages about subscription.
2146 # - Managing irregularity with numbers.
2147 # - Adding Internal Notes in subscription management.
2148 # - Repeating Button above pages.
2150 # Please run Updatedatabase to change irregularity and add internalnotes field to subscription
2152 # Revision 1.157.2.52 2007/01/24 13:57:26 tipaul
2153 # - setting supplierid to auto_increment (HDL : could you check that is works, i'm not 100% sure)
2154 # - removing 22 -> 30 marc_subfield_table -> marcxml stuff, it's now in misc/migration_tools/22_to_30/
2156 # Revision 1.157.2.51 2007/01/18 09:58:45 tipaul
2157 # defaulting NOT NULL fields (to '')
2159 # Revision 1.157.2.50 2007/01/18 09:39:21 tipaul
2160 # issuedate must be defaulted with ' '
2162 # Revision 1.157.2.49 2007/01/18 09:37:30 tipaul
2163 # removing 2 field definitions that were here twice
2165 # Revision 1.157.2.48 2007/01/15 09:55:40 toins
2166 # adding a new logging systempref : FinesLog.
2168 # Revision 1.157.2.47 2007/01/12 18:09:49 toins
2171 # Revision 1.157.2.46 2007/01/11 14:35:39 tipaul
2172 # adding Opac Browser feature : the build_browser_and_cloud.pl script will :
2173 # - fill the browser table, that enable browsing, digit by digit of a given category, the catalogue. A complete dewey classification is provided in the script, active only for french libraries, of course (although, for instance, the script check that the catalogue is in english for developping convenience)
2174 # - fill the tags table, that contains the subject cloud.
2176 # The cloud part is a copy of the previous build_tags.pl script that can be deleted : those 2 scripts require to parse all the catalogue to extract interesting data, so they are long. It's useless to parse the catalogue twice !
2178 # The commit also add the systempreference to hide/show the OpacBrowse in database & in systempref management script.
2180 # IMPROVEMENTS to do :
2181 # - the script that builds the tables can be improved to update only last week biblios (at the price of a small error in value links, but it's not a problem).
2182 # - add, in parameters section, a place to edit browser descriptions. The build script has to be updated to to avoid deleting existing browser descriptions.
2184 # Revision 1.157.2.45 2007/01/10 16:52:52 toins
2185 # Value for Log Features syspref are set to 0 by default.
2187 # Revision 1.157.2.44 2007/01/10 16:31:15 toins
2188 # new systems preferences :
2189 # - CataloguingLog (log the update/creation/deletion of a notice if set to 1)
2190 # - BorrowersLog ( idem for borrowers )
2191 # - IssueLog (log all issue if set to 1)
2192 # - ReturnLog (log all return if set to 1)
2193 # - SusbcriptionLog (log all creation/deletion/update of a subcription)
2195 # All of theses are in a new tab called 'LOGFeatures' in systempreferences.pl
2197 # Revision 1.157.2.43 2007/01/10 14:13:17 toins
2198 # opac_news.displayed is replaced by opac_news.number.
2199 # This field say how are ordered the news on the template.
2201 # Revision 1.157.2.42 2007/01/09 14:09:01 toins
2202 # 2 field added to opac_news.('expirationdate' and 'displayed').