Source

gestiona / src / sql / creacionfunciones.sql

Full commit
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
BEGIN;

-- Recibe un valor y el tipo de cuenta, y retorna el valor absoluto
--  alineado si queda en débitos, cuando está en créditos, retornará 
-- el valor absoluto
-- El tipo de cuenta es 1 y si es de tipo débito, -1 si es de tipo
-- crédito.
-- Ejemplo de uso :
-- SELECT alinumero(5,-1);
-- Retornará el 5 no alineado.
-- SELECT alinumero(-5,-1);
-- Retornará el 5 alineado.
-- el 15 de Enero de 2004
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION alinumero(int8,int) RETURNS text
AS '
num=args[0]
signo=args[1]
if num==0 :
   if signo == 1 :
      return "0        ."
   else : 
      return "0"
else :
   a=int(num/abs(num))
if a*signo>0 :
   return str(abs(num))+"         ."
return str(abs(num))
'
LANGUAGE plpythonu;




-- Recibe el identificador de una cuenta y una fecha válida, separada
-- por /
-- Calcula el saldo antes de la fecha especificada y lo retorna
-- Ejemplo de uso :
-- SELECT saldodecuenta(5,'16/01/2004');
-- Calcularía el saldo de la cuenta con id 5 'Cajas Menores 110510' hasta
-- el 15 de Enero de 2004
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION saldodecuenta(int4,text) RETURNS numeric
AS '
cuenta=args[0]
fecha=args[1]
anio=fecha.split("/")[2]
saldo=0.0
naturaleza=plpy.execute("SELECT naturaleza FROM tiposcuenta WHERE id=%d" % cuenta)[0]["naturaleza"]
#Se obtiene el saldo del último período calculado
q="SELECT pc.anterior AS anterior,(s.debito-s.credito)*ti.naturaleza AS saldo FROM periodoscontables pc,saldos s,tiposcuenta ti WHERE nombre=''Enero %s'' AND pc.anterior=s.idperiodo AND ti.id=s.idtiposcuenta AND s.activo=1 AND s.idtiposcuenta=%d" %(anio,cuenta)
res1=plpy.execute(q)
if len(res1)>0 :
  #Se toma el saldo inicial para la cuenta si había saldo
  saldo=res1[0]["saldo"]
  periodo=res1[0]["anterior"]
else :
  #Dado que la cuenta no tenía saldo, se comienza en cero, y se obtiene el período contable inicial del año.
  periodo=(plpy.execute("SELECT anterior FROM periodoscontables WHERE nombre=''Enero %s''" % anio)[0]["anterior"])
#Se calcula el movimiento entre el último período calculado y la fecha especificada
q="SELECT SUM(tc.valor*tc.signo) AS valor FROM transaccionescuenta tc, transacciones t WHERE t.id=tc.idtransaccion AND t.idperiodo>%d AND date_lt(t.fecha,date(''%s'')) AND tc.idcuenta = %d  AND tc.idestado=1 AND t.idestado=1" % (periodo,fecha,cuenta)
res2=plpy.execute(q)
if len(res2)>0 :
  if res2[0]["valor"]!=None :
    #En caso de que hubiera movimientos, estos se adicionan.
    saldo=saldo+res2[0]["valor"]*naturaleza
return saldo*naturaleza
'
LANGUAGE plpythonu;


-- Recibe el año para el cuál se va a hacer ajuste al peso a 
-- cuentas que tengan un saldo inferior a un valor dado, y el
-- id del usuario que registra, los ajustes al peso se harían
-- en el período de cancelación y la fecha en que deberá aparecer
-- Registrada la transacción
-- Ejemplo de uso :
-- SELECT ajustarpeso(2004,5000,13,'2005-01-01')
-- Tomaría todas las subcuentas cuyos saldos sean inferiores a $5000
-- para hacerles ajuste al peso colocando en la cuenta correspondiente
-- por el usuario con id 13 el primero de enero de 2005
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION ajustarpeso(int4,int4,int4,text) RETURNS numeric
AS '
anio=args[0]
idtercero=args[2]
fregistro=args[3]

#Búsqueda del id de la transaccion
nronotai=1+plpy.execute("SELECT ultimatransaccion(id) from tiposcomprobante where abrevia=''NI''")[0]["ultimatransaccion"]
tiponota=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''NI''")[0]["id"]
res=plpy.execute("SELECT id,fechaini FROM periodoscontables WHERE nombre=''Cancela %d''" % anio)
if (len(res)==0) :
  #No existía período contable para el año en mención.
  return -1
idperiodo=res[0]["id"]
fecha=res[0]["fechaini"]
res=plpy.execute("INSERT INTO transacciones(idcomprobante,fecha,descripcion,tipotercero,idtercero,idestado,idusuario,fecharegistro,idperiodo,idtipocomprobante) VALUES (%d,''%s'',''Ajustes al peso %d'',%d, %d,%d,%d,''%s'',%d,%d)" % (nronotai,fecha,anio,3,idtercero,1,idtercero,fregistro,idperiodo,tiponota))

#Se toma el id para las transaccionescuenta
trans=plpy.execute("SELECT max(id) from transacciones WHERE idtipocomprobante=%d AND descripcion=''Ajustes al peso %d''" % (tiponota,anio))[0]["max"]

#plpy.info("SELECT  ti.id,ti.naturaleza AS signo,ti.oficial AS cuenta ,sum(tc.valor*tc.signo) AS saldo FROM tiposcuenta ti, transaccionescuenta tc, transacciones t WHERE t.id=tc.idtransaccion AND t.idestado=1 AND tc.idestado=1 AND t.idperiodo<%d AND ti.id=tc.idcuenta AND (ti.oficial LIKE ''%s'' OR ti.oficial LIKE ''%s'') GROUP BY ti.oficial,ti.descripcion,ti.id,ti.naturaleza HAVING sum(tc.valor*tc.signo)<> 0 AND @sum(tc.valor*tc.signo)<%d ORDER BY text(ti.oficial)" % (idperiodo,"1%","2%",args[1]))
res=plpy.execute("SELECT  ti.id,ti.naturaleza AS signo,ti.oficial AS cuenta ,sum(tc.valor*tc.signo) AS saldo FROM tiposcuenta ti, transaccionescuenta tc, transacciones t WHERE t.id=tc.idtransaccion AND t.idestado=1 AND tc.idestado=1 AND t.idperiodo<%d AND ti.id=tc.idcuenta AND (ti.oficial LIKE ''%s'' OR ti.oficial LIKE ''%s'') GROUP BY ti.oficial,ti.descripcion,ti.id,ti.naturaleza HAVING sum(tc.valor*tc.signo)<> 0 AND @sum(tc.valor*tc.signo)<%d ORDER BY text(ti.oficial)" % (idperiodo,"1%","2%",args[1]))

total=0.0
hechas=1
for ar in res :
  total=total+ar["saldo"]
  if ar["signo"]==-1 :
    if ar["saldo"]>0:
      valor=ar["saldo"]
      signo=-1
    else :
      signo=1
      valor=-ar["saldo"]
  else :
    if ar["saldo"]>0:
      valor=ar["saldo"]
      signo=-1
    else :
      signo=1
      valor=-ar["saldo"]
  #plpy.info("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,%d,1)" % (trans,ar["id"],valor,signo))
  plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,%d,1)" % (trans,ar["id"],valor,signo))
  hechas+=1
if total>0.0 :
 #plpy.info("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,1,1)" % (trans,1583,total))
 plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,1,1)" % (trans,1583,total))
else :
 #plpy.info("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%f,%s,-1,1)" % (trans,3853,-total))
 plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,-1,1)" % (trans,3853,-total))
return hechas
'
LANGUAGE plpythonu;


-- Recibe el año para el cuál se va a hacer ajuste al peso a 
-- cuentas que tengan un saldo inferior a un valor dado, y el
-- id del usuario que registra, los ajustes al peso se harían
-- en el período de cancelación, la fecha en que deberá aparecer
-- Registrada la transacción y como último parámetro recibe una 
-- cadena de la forma ,id0,id1,....,idn, en la cuál aparecerán 
-- los ids de las tiposcuenta que pueden estar incluidas en el 
-- ajuste al peso.una cadena de filtro.
-- Incluye únicamente los grupos 1 y 2
-- Ejemplo de uso :
-- SELECT ajustarpeso(2004,5000,13,'2005-01-01',',10,40,3027,')
-- Tomaría todas las subcuentas cuyos saldos sean inferiores a $5000
-- para hacerles ajuste al peso colocando en la cuenta correspondiente
-- por el usuario con id 13 el primero de enero de 2005, incluyendo única
-- mente los saldos de las cuentas cuyo id es 10, 40 y 3027
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION ajustarpeso(int4,int4,int4,text,text) RETURNS numeric
AS '
anio=args[0]
idtercero=args[2]
fregistro=args[3]
filtro=args[4]

#Búsqueda del id de la transaccion
nronotai=1+plpy.execute("SELECT ultimatransaccion(id) from tiposcomprobante where abrevia=''NI''")[0]["ultimatransaccion"]
tiponota=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''NI''")[0]["id"]
res=plpy.execute("SELECT id,fechafin-1 as fechafin FROM periodoscontables WHERE nombre=''Diciembre %d''" % anio)
if (len(res)==0) :
  #No existía período contable para el año en mención.
  return -1
idperiodo=res[0]["id"]
fecha=res[0]["fechafin"]
res=plpy.execute("INSERT INTO transacciones(idcomprobante,fecha,descripcion,tipotercero,idtercero,idestado,idusuario,fecharegistro,idperiodo,idtipocomprobante) VALUES (%d,''%s'',''Ajustes al peso %d'',%d, %d,%d,%d,''%s'',%d,%d)" % (nronotai,fecha,anio,3,idtercero,1,idtercero,fregistro,idperiodo,tiponota))

#Se toma el id para las transaccionescuenta
trans=plpy.execute("SELECT max(id) from transacciones WHERE idtipocomprobante=%d AND descripcion=''Ajustes al peso %d''" % (tiponota,anio))[0]["max"]

res=plpy.execute("SELECT  ti.id,ti.naturaleza AS signo,ti.oficial AS cuenta ,sum(tc.valor*tc.signo) AS saldo FROM tiposcuenta ti, transaccionescuenta tc, transacciones t WHERE t.id=tc.idtransaccion AND t.idestado=1 AND tc.idestado=1 AND t.idperiodo<%d AND ti.id=tc.idcuenta AND (ti.oficial LIKE ''%s'' OR ti.oficial LIKE ''%s'') GROUP BY ti.oficial,ti.descripcion,ti.id,ti.naturaleza HAVING sum(tc.valor*tc.signo)<> 0 AND @sum(tc.valor*tc.signo)<%d ORDER BY text(ti.oficial)" % (idperiodo,"1%","2%",args[1]))

total=0.0
hechas=1
for ar in res :
  if ","+`ar["id"]`+","  in filtro :
    total=total+ar["saldo"]
    if ar["signo"]==-1 :
      if ar["saldo"]>0:
        valor=ar["saldo"]
        signo=-1
      else :
        signo=1
        valor=-ar["saldo"]
    else :
      if ar["saldo"]>0:
        valor=ar["saldo"]
        signo=-1
      else :
        signo=1
        valor=-ar["saldo"]
    plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,%d,1)" % (trans,ar["id"],valor,signo))
    hechas+=1
if total>0.0 :
 plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,1,1)" % (trans,3853,total))
else :
 plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,-1,1)" % (trans,1583,-total))
return hechas
'
LANGUAGE plpythonu;


-- Recibe el año del período a cerrar, los dígitos de la cuenta
-- donde se almacenaría el resultado del ejercicio, el id del tercero
-- que registra la transacción, fecha en que la registra.
--
-- Cruza todas las subcuentas de los grupos 4 y 5 y el saldo lo coloca
-- en la cuenta especificada por el usuario.
-- Ejemplo de uso :
-- SELECT cierreperiodo(2004,'370503',13);
-- Adiciona en la cuenta 3705'dos últimos dígitos' el período 2004 el
-- primero de enero del 2005, por el usuario con identificador 13
-- Requiere que se haya creado el lenguaje previameannte para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION cierreperiodo(int4,text,int4) RETURNS numeric
AS '
anio=args[0].
cuenta=args[1]
idtercero=args[2]

#Búsqueda de la cuenta donde se colocará el resultado del ejercicio
try :
   nrocuenta=plpy.execute("SELECT id from tiposcuenta WHERE oficiali::text=''%s''" % cuenta)[0]["id"]
except :
   #No existía la cuenta en donde se iba a almacenar el resultado
   return -2
#Búsqueda del id de la transaccion
nronotai=1+plpy.execute("SELECT ultimatransaccion(id) from tiposcomprobante where abrevia=''NI''")[0]["ultimatransaccion"]
tiponota=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''NI''")[0]["id"]
res=plpy.execute("SELECT id,fechaini FROM periodoscontables WHERE nombre=''Cancela %d''" % anio)
if (len(res)==0) :
  #No existía período de cancelación para el año en mención.
  return -1
idperiodo=res[0]["id"]
fecha=res[0]["fechaini"]
res=plpy.execute("INSERT INTO transacciones(idcomprobante,fecha,descripcion,tipotercero,idtercero,idestado,idusuario,fecharegistro,idperiodo,idtipocomprobante) VALUES (%d,''%s'',''Cierre del período %d'',%d, %d,%d,%d,date(''now''),%d,%d)" % (nronotai,fecha,anio,3,idtercero,1,idtercero,idperiodo,tiponota))

#Se toma el id para las transaccionescuenta
plpy.execute("SELECT max(id) from transacciones WHERE idtipocomprobante=%d AND descripcion=''Cierre del período %d''" % (tiponota,anio))
trans=plpy.execute("SELECT max(id) from transacciones WHERE idtipocomprobante=%d AND descripcion=''Cierre del período %d''" % (tiponota,anio))[0]["max"]

#Se calculan los saldos de todas las cuentas 4 y 5 presentes que no sean cero.
res=plpy.execute("SELECT ti.id,ti.oficial||'' ''||ti.descripcion AS cuenta, sum(tc.valor*tc.signo) AS saldo  FROM tiposcuenta ti, transaccionescuenta tc, transacciones t, periodoscontables pc WHERE t.id=tc.idtransaccion AND t.idestado=1 AND tc.idestado=1 AND t.idperiodo=pc.id AND pc.nombre like ''%"+`anio`+"'' AND ti.id=tc.idcuenta AND (ti.oficial::text like ''4%'' OR ti.oficial::text like ''5%'')GROUP BY ti.oficial, ti.descripcion, ti.id HAVING sum(tc.valor*tc.signo)<> 0 ORDER BY text(ti.oficial)")
i=1
debe=0.0
haber=0.0
for ar in res :
  if ar["cuenta"][0]=="4" :
    haber=haber+ar["saldo"]
    if ar["saldo"]>0:
      valor=ar["saldo"]
      signo=-1
    else :
      signo=1
      valor=-ar["saldo"]
  else :
    debe=debe+ar["saldo"]
    if ar["saldo"]>0:
      valor=ar["saldo"]
      signo=-1
    else :
      signo=1
      valor=-ar["saldo"]
  plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES (%d,%d,%s,%d,1)" % (trans,ar["id"],valor,signo))
  i+=1
#Se calcula la resta de 4 y 5 y se coloca en una cuenta del 3.
#Se calcula pérdida
saldo=debe+haber
signo=1
if saldo<0 :
  #En realidad fue ganancia
  signo=-1
  saldo=-saldo

plpy.execute("INSERT INTO transaccionescuenta(idtransaccion,idcuenta,valor,signo,idestado) VALUES(%d,%d,%s,%d,1)" % (trans,nrocuenta,saldo,signo))
return i+1
'
LANGUAGE plpythonu;


-- Recibe el identificador del anio para el cuál se calculan
-- los saldos.
-- Aquellas cuentas que queden saldas NO serán incluídas en los
-- saldos, únicamente aquellas que queden con un saldo.
-- Depende de los saldos del año anterior y de los movimientos
-- del año a saldar.
-- Ejemplo de uso :
-- SELECT saldosparaperiodo(2004);
-- Saldaría el período 2004.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION saldosparaperiodo(int4) RETURNS int
AS '
anio=args[0]
panterior=plpy.execute("SELECT anterior FROM periodoscontables WHERE nombre=''Enero %d''" % anio)[0]["anterior"]
pultimo=plpy.execute("SELECT id FROM periodoscontables WHERE nombre=''Cancela %d''" % anio)[0]["id"]
plpy.execute("INSERT INTO saldos (idperiodo,idtiposcuenta,debito,credito,activo) SELECT %d,int4(s.id),@s.v* @(sign(s.v)+s.n)/2,@s.v* @(sign(s.v)-s.n)/2,1 FROM (SELECT coalesce(saldos.id,mov.id) AS id,haganumero(saldos.inicial)+haganumero(mov.movimiento) AS v,int4(coalesce(saldos.naturaleza,mov.naturaleza)) AS n FROM (SELECT ti.id AS id,(sum(s.debito)-sum(s.credito))*ti.naturaleza AS inicial, ti.naturaleza AS naturaleza FROM saldos s, tiposcuenta ti WHERE s.idtiposcuenta= ti.id AND s.idperiodo=%d GROUP BY ti.naturaleza , ti.id) AS saldos FULL OUTER JOIN (SELECT ti.id AS id, SUM(tc.valor*tc.signo)*ti.naturaleza AS movimiento, ti.naturaleza FROM tiposcuenta ti, transaccionescuenta tc , transacciones t WHERE tc.idestado=1 AND t.idestado=1 AND ti.id=tc.idcuenta AND t.id=tc.idtransaccion AND t.idperiodo>%d AND t.idperiodo<=%d GROUP BY ti.id,ti.naturaleza HAVING @SUM(tc.valor*tc.signo)*ti.naturaleza>=1) AS mov ON mov.id=saldos.id GROUP BY saldos.id,mov.id,saldos.inicial,mov.movimiento,saldos.naturaleza,mov.naturaleza  HAVING  haganumero(saldos.inicial)+haganumero(mov.movimiento)<>0) AS s" % (pultimo,panterior,panterior,pultimo))
return plpy.execute("SELECT sum(activo) FROM saldos WHERE activo=1 AND idperiodo=%d GROUP BY idperiodo" % pultimo)[0]["sum"]
'
LANGUAGE plpythonu;




-- Recibe dos fechas, la fecha de nacimiento y la fecha con la que se desea
-- calcular la edad, retorna la edad en años.  Formato YYYY/dd/mm
-- Ejemplo :
-- SELECT edad('1974-01-06','2005-01-01');
-- Requiere que se haya creado el lenguaje
-- previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION edad(text,text) RETURNS int
AS 'i=[int(a) for a in args[0].split("-")]
j=[int(a) for a in args[1].split("-")]
b=j[0]-i[0]
if b>0 :
  if j[1]>i[1] :
     return j[0]-i[0]
  elif j[1]==i[1] and j[2]>=i[2] :
     return j[0]-i[0]
  return j[0]-i[0]-1
return 0'
LANGUAGE plpythonu;

-- Recibe un arreglo y un valor, decidiendo si el valor está en el arreglo
-- No importa el tipo de los elementos del arreglo y del segundo parámetro
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
-- Ejemplo de uso :
-- select esta(array[1,2,3],6);
-- retorna false
-- select esta(array[1,2,3],'3');
-- retorna true
CREATE OR REPLACE FUNCTION esta(anyarray,text) RETURNS boolean
AS 'return args[0].count(args[1])>0'
LANGUAGE plpythonu;

-- Recibe dos enteros, retorna la suma de los dos, cuando encuentra None
-- asume que el valor es 0
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
-- Ejemplo de uso :
-- select sumajoin(2,2);
-- retorna 4
-- select sumajoin(2,null);
-- retorna 2
-- select sumajoin(null,null);
-- retorna 0
CREATE OR REPLACE FUNCTION sumajoin(bigint,bigint) RETURNS bigint
   AS '
if args[0]==None :
  if args[1]==None :
    return 0
  return args[1]
elif args[1]==None :
  return args[0]
else:
  return args[0]+args[1]
'
LANGUAGE plpythonu;



-- Recibe un número o null, si es null retorna 0, de lo contrario el
-- número que recibió.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
-- Ejemplo de uso :
-- select haganumero(null);
-- retorna 0
-- select haganumero(3.45);
-- retorna 3.45
CREATE OR REPLACE FUNCTION haganumero(float) RETURNS float
  AS '
if args[0]==None :
  return 0
else :
  return args[0]
'
LANGUAGE plpythonu;


-- Recibe un id de una cuenta.
-- retorna el nombre completo de la cuenta
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
-- Ejemplo de uso :
-- select nombrecuenta(12);
-- retorna "ACTIVO  INVERSIONES  CUENTAS EN PARTICIPACION  AJUSTES POR INFLACION"
-- select nombrecuenta(1470);
-- retorna "INGRESOS  NO OPERACIONALES  SERVICIOS  DE TRANSPORTE PROGRAMA GAS NATURAL"
CREATE OR REPLACE FUNCTION nombrecuenta(int) RETURNS text
AS '
res=plpy.execute("SELECT hijade,descripcion FROM tiposcuenta WHERE id=%d" % args[0])
if res[0]["hijade"]==-1 :
  return res[0]["descripcion"]
res2=plpy.execute("SELECT nombrecuenta(%d)" % res[0]["hijade"])
return  res2[0]["nombrecuenta"]+res[0]["descripcion"]'
LANGUAGE plpythonu;



-- Recibe un id de un estudiante válido y el año en el cuál se matriculó
-- Retorna el mes que debería estar pagando, en donde 0 representa a Febrero.
-- Ejemplo de uso :
-- SELECT mesapagar(230,2005);
-- Mostraría el mes que debería pagar el estudiante con id 230 matriculado durante
-- el 2005.
-- previamente para la base de datos debe haberse creado el lenguaje plpython.
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION mesapagar(int,int) RETURNS int
AS '
id=args[0]
anio=args[1]
aniom=plpy.execute("SELECT to_char(fecha,''YYYY/MM'') AS fecha FROM matriculas WHERE estudiante=%d AND periodo=%d" %(id,anio))[0]["fecha"]
cant=0

#Se revisa si tiene descuentos para hacer el ajuste correspondiente
if anio==int(aniom.split("/")[0]) and int(aniom.split("/")[1])>1 :
  #Se matriculó iniciado el período académico
  cons=plpy.execute("SELECT int4(round(sum(@tc.valor*tc.signo)/m.costopension,0)+int4(to_char(m.fecha,''MM''))-2) AS mesporpagar FROM transaccionescuenta tc,tiposcuenta ti,transacciones t, estudiantes e, matriculas m WHERE ti.id=tc.idcuenta AND t.id=tc.idtransaccion AND (ti.oficial = 1305050000000+int4(e.codigoestudiante) OR ti.oficial=2705450000000+int4(codigoestudiante) ) AND e.id=%d AND t.idestado=1 AND e.id=m.estudiante AND m.periodo=%d AND t.descripcion SIMILAR TO e.codigoestudiante||'':\\\\\\[%d%s'' GROUP BY m.costopension,m.fecha" % (id,anio,anio,"-(P|A)%"));
  if len(cons)==1 :
    #Ya ha hecho algún Pago
    return cons[0]["mesporpagar"]
  else :
    #Si no había hecho pago, se revisa el mes en el que se matriculó
    cant=plpy.execute("SELECT int4(to_char(fecha,''MM''))-2 AS mes FROM matriculas WHERE estudiante=%d AND periodo=%d" %(id,anio))[0]["mes"]
else :
  #Se matriculó ANTES de iniciar el período.
  cons=plpy.execute("SELECT int4(round(sum(@tc.valor*tc.signo)/m.costopension,0)) AS mesporpagar FROM transaccionescuenta tc,tiposcuenta ti,transacciones t, estudiantes e, matriculas m WHERE ti.id=tc.idcuenta AND t.id=tc.idtransaccion AND (ti.oficial = 1305050000000+int4(e.codigoestudiante) OR ti.oficial=2705450000000+int4(codigoestudiante) ) AND e.id=%d AND t.idestado=1 AND e.id=m.estudiante AND m.periodo=%d AND t.descripcion SIMILAR TO e.codigoestudiante||'':\\\\\\[%d%s'' GROUP BY m.costopension" % (id,anio,anio,"-(P|A)%"));
  if len(cons)==1 :
    #Ya ha hecho algún Pago
    return cons[0]["mesporpagar"]
#No había hecho el primer pago de pensión
return cant
'
LANGUAGE plpythonu;

-- Recibe el nombre y el primer apellido de la persona y retorna su nuevo
-- login, de acuerdo a los login previamente colocados en las tablas
-- empleados y estudiantes
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION nuevologin(text,text) RETURNS text
AS $$
cad1=args[0]
cad2=args[1]
ini="áàéèíìóòúùüñÁÀÉÈÍÌÓÒÚÙÜÑ"
rem="aaeeiioouuunaaeeiioouuun"
q="SELECT translate ('%s','%s','%s') AS trans1, translate ('%s','%s','%s') AS trans2" % (cad1,ini,rem,cad2,ini,rem)
myt=plpy.execute(q)
login=myt[0]["trans1"][0:3]+myt[0]["trans2"][0:3]
plan = plpy.prepare("SELECT DISTINCT login FROM estudiantes WHERE login LIKE $1 UNION SELECT login FROM empleados WHERE login LIKE $1 UNION SELECT login FROM datospersonalesusuario WHERE login like $1 ORDER BY login DESC", ["text"])
rv = plpy.execute(plan, [ login+"%" ])
if len(rv)==0 :
 return login[:6]
elif reduce(lambda x,y:x or y,[i["login"]==login for i in rv])==0:
 return login
else :
 j=2
 while [i["login"] for i in rv].count(login+str(j))>0 :
   j=j+1
 return login[:6]+str(j-1)
$$ LANGUAGE plpythonu;

CREATE OR REPLACE FUNCTION nuevocodigo(int) RETURNS int
AS '
res=plpy.execute("SELECT int4(max(codigoestudiante))+1 AS codigo FROM estudiantes WHERE codigoestudiante LIKE (SELECT to_char(d.fechanacimiento,''YYYY'')||''%s'' FROM datospersonales d WHERE id=%d)  UNION  SELECT int4(to_char(d.fechanacimiento,''YYYY'')) AS codigo FROM datospersonales d WHERE id=%d ORDER BY codigo DESC" %("%",args[0],args[0]))
if res[0]["codigo"]==None or res[1]["codigo"]==None:
  #Se crea un nuevo código
  return (res[1]["codigo"]*1000)+1
else :
  #Se Crea un consecutivo
  return res[0]["codigo"]

'
LANGUAGE plpythonu;

-- Recibe el id de alguien de datos personales, retorna el
-- nombre completo, si algún valor era nulo, arma el nombre con los valores
-- no nulos.  Si los tres componentes son nulos, retorna una cadena vacía.
-- Ejemplo :
-- SELECT nombre(13);
-- Retornaría el nombre de la persona con id 13.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION nombre(int4) RETURNS text
AS '
a=""
id=args[0]
res1=plpy.execute("SELECT nombres,apellido1,apellido2 FROM datospersonales WHERE id=%d" % (id) )
if len(res1)==0 :
 return a
i=0
if res1[0]["nombres"]!=None :
 a=res1[0]["nombres"]
if res1[0]["apellido1"]!=None :
 a=a+" "+res1[0]["apellido1"]
if res1[0]["apellido2"]!=None :
 a=a+" "+res1[0]["apellido2"]
return a
'
LANGUAGE plpythonu;

-- Recibe tres cadenas como nombre, apellido1, y apellido2, retorna el
-- nombre completo, si algún valor era nulo, arma el nombre con los valores
-- no nulos.  Si los tres parámetros son nulos, retorna una cadena vacía.
-- Ejemplo :
-- SELECT nombre('Arnulfo','Gómez','Perez');
-- Retornaría 'Arnulfo Gómez Pérez'
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION nombre(text,text,text) RETURNS text
AS '
a=""
res1={"nombres":args[0],"apellido1":args[1],"apellido2":args[2]}

if res1["nombres"]!=None :
 a=res1["nombres"]
if res1["apellido1"]!=None :
 a=a+" "+res1["apellido1"]
if res1["apellido2"]!=None :
 a=a+" "+res1["apellido2"]
return a
'
LANGUAGE plpythonu;


-- Recibe un id de una institución y retorna el nombre con el nit
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION empresa(int4) RETURNS text
AS '
a=""
id=args[0]
res1=plpy.execute("SELECT nombre,nit FROM instituciones WHERE id=%d" % (id) )
if len(res1)==0 :
 return a
if res1[0]["nombre"]!=None :
  a=a+res1[0]["nombre"]
if res1[0]["nit"]!=None :
  a=a+" Nit :"+res1[0]["nit"]
return a
'
LANGUAGE plpythonu;

-- Recibe un id de un tercero y un tipo de tercero, retorna el nombre del 
-- tercero identificando si es una institución o una persona.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION infotercero(int4,int4) RETURNS text
AS '
tipo=args[1]
id=args[0]
res=plpy.execute("SELECT substr(descripcion,9) AS tipo FROM variables WHERE nombre=''tipotercero'' AND valor=%d::text" % tipo)
if len(res)==0 :
 return ""
if res[0]["tipo"]=="Institución -> NIT" :
 res2=plpy.execute("SELECT empresa(%d)" % (id))
 if len(res2)>0 :
   return res2[0]["empresa"]
else :
 res2=plpy.execute("SELECT coalesce(valordocid,''PLEASE FILL VALDOCID'')||'' ''||nombre(id) AS nombre FROM datospersonales WHERE id=%d" % (id))
 if len(res2)>0 :
   return  res2[0]["nombre"]
return ""
'
LANGUAGE plpythonu;

-- Recibe el identificador de un tipo de transacción y retorna el 
-- siguiente id para el tipo de transacción, en caso de que
-- la transacción sea un comprobante de egreso toma el valor del
-- último comprobante de egreso, si es una consignación o una
-- transacción por Internet retorna 0, en cualquier otro caso
-- retorna el consecutivo siguiente máximo.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION ultimatransaccion(int4) RETURNS int
AS
'
tipo=args[0]
res=plpy.execute(" SELECT max(t.idcomprobante) FROM transacciones t WHERE t.idtipocomprobante=%d AND to_char(t.fecha,''YYYY'')=(SELECT valor FROM variables WHERE nombre=''periodoactual'')" % tipo)
if len(res)==0 or res[0]["max"]==None :
 return 1
if tipo==1 or tipo==7 :
 return res[0]["max"]
elif tipo==3 :
 return 0
else :
 return res[0]["max"]+1
'
LANGUAGE plpythonu;

-- Recibe una cadena que representa las transaccionescuenta a adicionar de la
-- siguiente forma :
-- Cada transacción viene separada con | , y dentro de cada una hay 4 campos
-- separados por (,), en los cuáles el primero es el código inicial de la
-- cuenta que se afectaría, el segundo posible sufijo para la subcuenta, que puede
-- no tener parámetro, el tercero valor en débitos, el cuarto valor en créditos
-- Como segundo parámetro recibe el identificador de la transacción a la cual
-- irán asociadas las transaccionescuenta que se crearían.
-- Retorna la cantidad de registros que se adicionan a transaccionescuenta
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION registratransacciones(text,int4) RETURNS int
AS
'
a=args[0].split("|")
for i in a :
  b=i.split(",")
  if b[2]==''0'' :
    plpy.execute("INSERT INTO transaccionescuenta(idcuenta,valor,signo,idestado,idtransaccion) VALUES ((SELECT id FROM tiposcuenta WHERE oficial=%s%s),%s,-1,1,%d)" % (b[0],b[1],b[3],args[1]))
  else :
    plpy.execute("INSERT INTO transaccionescuenta(idcuenta,valor,signo,idestado,idtransaccion) VALUES ((SELECT id FROM tiposcuenta WHERE oficial=%s%s),%s,1,1,%d)"%(b[0],b[1],b[2],args[1]))
return len(a)
'
LANGUAGE plpythonu;

-- Registra una transacción asociando los movimientos de las cuentas involucradas
-- Recibe como parámetro el tipo de tercero, el id del tercero, la fecha, la
-- fecha de registro, la descripción de la transacción, el id del usuario que 
-- registra, el id del modelo de la transaccion, una cadena de texto que 
-- representa las cuentas que serán afectadas con el mismo formato que el
-- procedimiento registratransacciones, el id de la transacción y el tipo de
-- comprobante.
-- Ejemplo :
-- registratransaccion(1,34,'03/01/2004','03/05/2004','Compra de algo',26,34,'111005,,30000,0|531015,,0,30000',342,3)
-- Representaría que el tercero con id 34 y tipo de documento de identidad 1 tiene asociada la transacción llamada
-- Compra de algo, se afectaron las cuentas 111005 y 531015 con el modelo de comprobante 34 el 3 de Enero de 2004 
-- registrado por la persona con id 26 el 3 de Mayo de 2004 con tipo de comprobante 3 y número de comprobante 342

CREATE OR REPLACE FUNCTION registratransaccion(int4,int4,date,date,text,int4,int4,text,int4,int4) RETURNS int
AS
'
tipotercero=args[0]
idtercero=args[1]
fecha=args[2]
fecharegistro=args[3]
descripcion=args[4]
registra=args[5]
idmodelo=args[6]
cuentasafectadas=args[7]
idcomprobante=args[8]
tipocomprobante=args[9]
res=1
i1="INSERT INTO transacciones (idcomprobante,fecha,descripcion,tipotercero,idtercero,idestado,idusuario,fecharegistro,idperiodo,idmodelostransaccion,idtipocomprobante) VALUES (%d,date(''%s''),''%s'',%d,%d,1,%d,date(''%s''),(SELECT id FROM periodoscontables WHERE date_le(fechaini,date(''%s'')) AND date_le(date(''%s''),fechafin) ORDER BY id LIMIT 1),%d,%d)" % (idcomprobante,fecha,descripcion,tipotercero,idtercero, registra , fecharegistro , fecha, fecha , idmodelo,tipocomprobante )
plpy.execute(i1)
q1="SELECT id from transacciones WHERE fecha=date(''%s'') AND descripcion=''%s'' AND tipotercero=%d AND idtercero=%d AND idusuario=%d AND fecharegistro=date(''%s'') AND idmodelostransaccion=%d AND idestado=1 ORDER BY id DESC LIMIT 1" %(fecha,descripcion,tipotercero,idtercero,registra,fecharegistro,idmodelo)
idtransaccion=plpy.execute(q1)[0]["id"]
i2="SELECT registratransacciones(''%s'',%d)" % (cuentasafectadas,idtransaccion)
res=res+plpy.execute(i2)[0]["registratransacciones"]
return res
'
LANGUAGE plpythonu;

-- Registra el pago de la matrícula acreditando pagos por anticipado en educación 
-- específica y debitando en la cuenta de bancos, recibe también el número de
-- consignación, en caso de que se reciba un 
-- valor de descuento, se crea el registro de la tabla descuento
-- Recibe una cadena con la fecha en la cuál aparecería realizada la transacción, 
-- el año, el valor del pago que hizo,
-- el código del estudiante, una descripción adicional, el identificador de quien
-- registra y la cantidad de descuento que se hace, usualmente es 0.
-- En caso de que la matrícula sea durante el período escolar, es decir, en febrero,
-- entonces se adiciona un registro a ingresos directamente y otra porción a pagos
-- anticipados por educación.
-- Retorna la cantidad de registros adicionados : 3
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION pagomatricula(text,int4,numeric,text,text,int4,int4,numeric,text) RETURNS int
AS
'
fecha=args[0]
anio=args[1]
valor=args[2]
codigoestudiante=args[3]
descripcion=args[4]
idregistra=args[5]
numconsigna=args[6]
descuento=args[7]
banco=args[8]
cadena="%s,,%s,0|270545,%s,0,%s" %(banco,valor,codigoestudiante,valor)
res=1
mes=int(fecha.split("/")[1])
if int(fecha.split("/")[2])==anio :
  #Se verifica si es una matrícula durante el año, en cuyo caso, una parte va directo a ingresos,
  #con la parte entera de la división entre 12.
  cadena="%s,,%s,0|270545,%s,0,%s|416005,%s,0,%s" %(banco,valor,codigoestudiante,(12-mes)*((valor-valor%12)/12),codigoestudiante,(mes*(valor-valor%12)/12)+valor%12)
if not descuento == 0 :
  #En caso de que haya un descuento en la matrícula, se registra en la tabla de descuentos.
  plpy.execute("INSERT INTO descuentos (persona,periodo,concepto,pago,descuento,fechainicial,fechafinal) VALUES ((SELECT id FROM estudiantes WHERE codigoestudiante=''%s''),%d,''%s[%d-M] ''||''%s'',%s,%s,date(''%s''),date(''%s'')) " %(codigoestudiante,anio,codigoestudiante,anio,descripcion,valor,descuento,fecha,fecha))
  res=res+1
  cadena="%s,,%s,0|417501,%s,%s,0|270545,%s,0,(%s+%s)" % (banco,valor,codigoestudiante,descuento,codigoestudiante,valor,descuento)
  if int(fecha.split("/")[2])==anio :
    #Si adicionalmente es una matrícula durante el año, una parte va a ingresos
    cadena="%s,,%s,0|417501,%s,%s,0|270545,%s,0,%s|416005,%s,0,%s" %(banco,valor,codigoestudiante,descuento,codigoestudiante,(12-mes)*((valor+descuento)-(valor+descuento)%12)/12,codigoestudiante,mes*(valor+descuento-(valor+descuento)%12)/12+(valor+descuento)%12)
  if plpy.execute("SELECT COUNT(*) FROM tiposcuenta WHERE oficial=417501%s" % codigoestudiante)[0]["count"]==0 :
    #Si la subcuenta de descuentos para el estudiante no existía, se crea.
    plpy.execute("INSERT INTO tiposcuenta(oficial,descripcion,hijade,naturaleza,puc) VALUES (417501%s,''Descuentos en costos educativos %s'',(SELECT id FROM tiposcuenta WHERE oficial=417501),-1,0)" %(codigoestudiante,codigoestudiante))
    res=res+1
plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES (''%s:[%d-M] Matricula estudiante %s %s'',date(''%s''),(SELECT id FROM periodoscontables WHERE date_le(fechaini,date(''%s'')) AND date_le(date(''%s''),fechafin)),1,date(''today''),1,(SELECT id FROM estudiantes WHERE codigoestudiante=%s),%d,(SELECT id FROM tiposcomprobante WHERE abrevia=''CO''),%d)" % (codigoestudiante,anio,codigoestudiante,descripcion,fecha,fecha,fecha,codigoestudiante,idregistra,numconsigna))
id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like ''%s:[%d-M]%s''" % (codigoestudiante,anio," Matricula estudiante%"))[0]["id"]
return res+plpy.execute("SELECT registratransacciones(''%s'',%d)" % (cadena,id))[0]["registratransacciones"]
return 0

'
LANGUAGE plpythonu;

-- Registra una transacción indicando que hizo el pago del estudiante por anticipado
-- acreditando la subcuenta de pagos por adelantado específica y debitando en 
-- la cuenta de bancos
-- Recibe una cadena con la fecha en la cuál aparecería realizada la transacción, 
-- el año, el mes(1 es Febrero, 10 es Noviembre), el valor del pago que hizo,
-- el código del estudiante, una descripción adicional, el identificador de quien
-- registra y el número de consignación.
-- Retorna la cantidad de registros adicionados : 3
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION pagoanticipado(text,int4,int4,numeric,text,text,int4,int4,text) RETURNS int
AS
'
meses=["Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre"]
fecha=args[0]
anio=args[1]
periodo=args[2]
valor=args[3]
codigoestudiante=args[4]
descripcion=args[5]
idregistra=args[6]
nroconsigna=args[7]
banco=args[8]
tipoc=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''CO''")[0]["id"]
plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES (''%s:[%d-A%d] Pago anticipado mes(es) %s estudiante %s %s'',date(''%s''),(SELECT id FROM periodoscontables WHERE date_le(fechaini,date(''%s'')) AND date_le(date(''%s''),fechafin)),1,date(''today''),1,(SELECT id FROM estudiantes WHERE codigoestudiante=%s),%d,%d,%d)" % (codigoestudiante,anio,periodo,meses[periodo-1],codigoestudiante,descripcion,fecha,fecha,fecha,codigoestudiante,idregistra,tipoc,nroconsigna))
id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like ''%s:[%d-A%d]%s''" % (codigoestudiante,anio,periodo," Pago anticipado mes(es) %"))[0]["id"]
res=plpy.execute("SELECT registratransacciones(''%s,,%s,0|270545,%s,0,%s'',%d)" % (banco,valor,codigoestudiante,valor,id))[0]["registratransacciones"]
return res+1	
'
LANGUAGE plpythonu;

-- Recibe el año, y un número de 1 a 12, donde 1 es Enero y 12 es Diciembre
-- Requiere que los estudiantes tengan subcuenta creada de cuentas por cobrar,
-- así mismo, los estudiantes tienen subcuenta de ingresos.  Recibe además el
-- usuario que registra la transacción, el tipo de transacción y el número de
-- transacción.
-- Esta función hace la cancelación de la matrícula entre los 12 meses del año
-- tomando las cuentas cobradas por anticipado versus ingresos.
-- Ejemplo:
-- SELECT cancelamesmatricula(2005,1,13,4,312);
-- Se amortizaría el pago de la matrícula para el mes de enero y se registraría
-- a nombre del usuario con id 13.  El tipo de transacción es número 4 y el
-- número de transacción 312.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION cancelamesmatricula(int4,int4,int4,int4,int4) RETURNS int
AS $$
meses=["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"]
anio=args[0]
periodo=args[1]
usuario=args[2]
tiponota=args[3]
nronotai=args[4]
pc=plpy.execute("SELECT id FROM periodoscontables WHERE date_le(fechaini,date('01/%d/%d')) AND date_le(date('01/%d/%d'),fechafin)" %(periodo,anio,periodo,anio))[0]["id"]
cant=0

#Se registra la cancelación mes a mes del costo de la matrícula para cada estudiante, 
#los que se matricularon tardíamente en el momento de la matrícula ya tienen una porción 
#descontada.  Aquellos que ya se retiraron igual continuarán con el mismo proceso de
#descuento mensual de pagos recibidos por anticipado.

#Se busca que en cada mes se descuenten partes enteras, por eso en Enero, se hacen ingresos
#mayores que en los otros meses.
if periodo==1 :
  query="SELECT e.codigoestudiante, (tc.valor-tc.valor%s12)/12+tc.valor%s12 AS valor, m.fecha FROM tiposcuenta ti, transaccionescuenta tc, transacciones t, estudiantes e, matriculas m WHERE tc.idtransaccion=t.id AND tc.idcuenta=ti.id AND ti.oficial::text='270545'||e.codigoestudiante AND m.periodo=%d AND e.id=m.estudiante AND t.descripcion like '%s' AND date_lt(m.fecha,date('01/01/%d')) AND t.idestado=1 AND tc.idestado=1 ORDER BY e.codigoestudiante" % ("%","%",anio,"%["+`anio`+"-M]%",anio)
else :
  query="(SELECT e.codigoestudiante, (tc.valor-tc.valor%s12)/12 AS valor, m.fecha FROM tiposcuenta ti, transaccionescuenta tc, transacciones t, estudiantes e, matriculas m WHERE tc.idtransaccion=t.id AND tc.idcuenta=ti.id AND ti.oficial::text='270545'||e.codigoestudiante AND m.periodo=%d AND e.id=m.estudiante AND t.descripcion like '%s' AND date_lt(m.fecha,date('01/01/%d')) AND t.idestado=1 AND tc.idestado=1 ORDER BY e.codigoestudiante) UNION (SELECT e.codigoestudiante, (tc.valor-tc.valor%s(12-int4(to_char(m.fecha,'MM'))))/(12-int4(to_char(m.fecha,'MM'))) AS valor , m.fecha FROM tiposcuenta ti, transaccionescuenta tc, transacciones t, estudiantes e, matriculas m WHERE tc.idtransaccion=t.id AND tc.idcuenta=ti.id AND ti.oficial::text='270545'||e.codigoestudiante AND m.periodo=%d AND e.id=m.estudiante AND t.descripcion like '%s' AND date_gt(date('01/%d/%d'),m.fecha) AND date_gt(m.fecha,date('01/01/%d')) AND t.idestado=1 AND tc.idestado=1 ORDER BY m.fecha,e.codigoestudiante)" % ("%",anio,"%["+`anio`+"-M]%",anio,"%",anio,"%["+`anio`+"-M]%",periodo,anio,anio)
res=plpy.execute(query)
for i in res :
  plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES ('%s:[%d-m%d] cancela mes a mes(%s) pago matrIcula estudiante %s',date('01/%d/%d'),%d,1,date('today'),1,(SELECT id FROM estudiantes WHERE codigoestudiante='%s'),%d,%d,%d)" % (i["codigoestudiante"],anio,periodo,meses[periodo-1],i["codigoestudiante"],periodo,anio,pc,i["codigoestudiante"],usuario,tiponota,nronotai))
  id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like '%s:[%d-m%d]%s' AND transacciones.idestado=1" %(i["codigoestudiante"],anio,periodo," cancela mes a mes%"))[0]["id"]
  cant=cant+plpy.execute("SELECT registratransacciones('270545,%s,%s,0|416005,%s,0,%s',%d)" % (i["codigoestudiante"],i["valor"],i["codigoestudiante"],i["valor"],id))[0]["registratransacciones"]
cant=cant+len(res)
return cant
$$
LANGUAGE plpythonu;

-- Recibe el año, un número de 0 a 11, donde 0 es enero y 11 es diciembre, el
-- id del usuario que registra la transacción y la opción de causación/amortización
--
-- Requiere que los estudiantes tengan subcuenta creada de cuentas por cobrar,
-- así mismo, los estudiantes tienen subcuenta de ingresos.
-- También requiere que los períodos estén ordenados, en sus ids, uno tras otro
-- consecutivamente
-- Esta función hace la causación de todos los estudiantes que se matricularon 
-- previamente y que están activos, también cancela el mes de la matrícula, y
-- registra como ingresos los pagos por anticipado de pensiones.
-- Para los meses de Enero y Diciembre, únicamente hace la cancelación de ingresos
-- versus cuentas cobradas por anticipado.
-- Ejemplo :
-- SELECT causar(2005,2,13,1)
-- Que amortizaría Marzo de 2005 a nombre del usuario identificado con id 13
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION causar(int4,int4,int4,int4) RETURNS int
AS $$
meses=["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"]
anio=args[0]
periodo=args[1]
usuario=args[2]
opcion=args[3]
#Se calcula el número de Nota Interna
nronotai=plpy.execute("SELECT ultimatransaccion(id) from tiposcomprobante where abrevia='NI'")[0]["ultimatransaccion"]
tiponota=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia='NI'")[0]["id"]
#Se Identifica el período del año en cuestión
per=plpy.execute("SELECT id AS id,p.nombre from periodoscontables p, (select min(anterior) AS ant from periodoscontables where nombre like '%s') AS sub WHERE p.anterior=sub.ant+%d" % ("%"+str(anio),periodo))
if len(per)==0 or opcion==0:
  #El período NO existía, o NO se cancelaba ni se causaba
  return 0
nomperiodo=per[0]["nombre"]
if opcion&1==1 and (nomperiodo.find("Enero %d" %anio)!=-1 or nomperiodo.find("Diciembre %d" %anio)!=-1 or opcion&2==0):
  #No es necesario causar pensiones.  Enero y Diciembre, o si se indica en opción que NO se causará.
  #Solamente se cancelan matrículas.
  return plpy.execute("SELECT cancelamesmatricula(%d,%d,%d,%d,%d)" % (anio,periodo+1,usuario,tiponota,nronotai))[0]["cancelamesmatricula"]

#Se hace causación de Pensiones
meses=["Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre"]
#Se obtiene el período contable a causar
pc=plpy.execute("SELECT id FROM periodoscontables WHERE date_eq(fechaini,date('01/%d/%d')) AND date_le(date('01/%d/%d'),fechafin)" %(periodo+1,anio,periodo+1,anio))[0]["id"]

cant=0
#Se causa únicamente los que están matriculados actualmente.  Primero los que tienen descuentos
q1="SELECT cods.codigoestudiante,d.pago,d.descuento,d.pago+d.descuento AS total FROM estudiantes e, descuentos d, ((SELECT e.codigoestudiante FROM estudiantes e, matriculas m WHERE e.id=m.estudiante AND m.periodo=%d AND m.activo=true AND date_gt(date('01/%d/%d'),m.fecha) UNION SELECT e.codigoestudiante FROM estudiantes e, matriculas m, retiros r WHERE e.id=m.estudiante AND r.id=e.id AND m.activo=false AND m.periodo=%d AND r.periodo=%d AND  date_lt(date('01/%d/%d'),r.fechasalida)) INTERSECT SELECT e.codigoestudiante FROM estudiantes e, matriculas m, descuentos d WHERE d.periodo=%d AND d.persona=e.id AND e.id=m.estudiante AND m.periodo=%d ) AS cods WHERE e.codigoestudiante=cods.codigoestudiante and d.periodo=%d AND d.persona=e.id" % (anio,periodo+2,anio,anio,anio,periodo+1,anio,anio,anio,anio)
res=plpy.execute(q1)
plpy.info(q1)

#
#C
#13
#417
#     416

for i in res :
  plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES ('%s:[%d-C%d] Causando mes %s estudiante %s',date('01/%d/%d'),%d,1,date('today'),1,(SELECT id FROM estudiantes WHERE codigoestudiante='%s'),%d,%d,%d)" % (i["codigoestudiante"],anio,periodo,meses[periodo-1],i["codigoestudiante"],periodo+1,anio,pc,i['codigoestudiante'],usuario,tiponota,nronotai))
  cadena="130505,%s,%f,0|417501,%s,%f,0|416005,%s,0,%f" % (i['codigoestudiante'],i['pago'],i['codigoestudiante'],i['descuento'],i['codigoestudiante'],i['total'])
  id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like '%s:[%d-C%d]%s'" % (i["codigoestudiante"],anio,periodo," Causando mes %"))[0]["id"]
  cant=cant+1+plpy.execute("SELECT registratransacciones('%s',%d)" % (cadena,id))[0]["registratransacciones"] 


#Ahora se causan los que NO tienen descuentos
q2="(SELECT e.codigoestudiante,m.costopension FROM estudiantes e, matriculas m WHERE e.id=m.estudiante AND m.periodo=%d AND m.activo=true AND date_gt(date('01/%d/%d'),m.fecha) UNION SELECT e.codigoestudiante,m.costopension FROM estudiantes e, matriculas m, retiros r WHERE e.id=m.estudiante AND r.id=e.id AND m.activo=false AND m.periodo=%d AND r.periodo=%d AND  date_lt(date('01/%d/%d'),r.fechasalida)) EXCEPT SELECT e.codigoestudiante,m.costopension FROM estudiantes e, matriculas m, descuentos d WHERE d.periodo=%d AND d.persona=e.id AND e.id=m.estudiante AND m.periodo=%d" % (anio,periodo+2,anio,anio,anio,periodo+1,anio,anio,anio)
plpy.info(q2)
res=plpy.execute(q2)
"""
C
13
    416
"""
for i in res :
  plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES ('%s:[%d-C%d] Causando mes %s estudiante %s',date('01/%d/%d'),%d,1,date('today'),1,(SELECT id FROM estudiantes WHERE codigoestudiante='%s'),%d,%d,%d)" % (i["codigoestudiante"],anio,periodo,meses[periodo-1],i["codigoestudiante"],periodo+1,anio,pc,i['codigoestudiante'],usuario,tiponota,nronotai))
  cadena="130505,%s,%f,0|416005,%s,0,%f" % (i['codigoestudiante'],i['costopension'],i['codigoestudiante'],i['costopension'])
  id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like '%s:[%d-C%d]%s'" % (i["codigoestudiante"],anio,periodo," Causando mes %"))[0]["id"]
  cant=cant+1+plpy.execute("SELECT registratransacciones('%s',%d)" % (cadena,id))[0]["registratransacciones"] 

if opcion&1==1:
   #Se cancela mes a mes el valor de la matrícula
   cant=cant+plpy.execute("SELECT cancelamesmatricula(%d,%d,%d,%d,%d)" % (anio,periodo+1,usuario,tiponota,nronotai))[0]["cancelamesmatricula"]

#Finalmente se ejecutan las cancelaciones concernientes a pagos por anticipado.
q3="SELECT -SUM(tc.valor*tc.signo) AS adelanto,m.costopension,e.codigoestudiante FROM transacciones t,tiposcuenta ti,transaccionescuenta tc,estudiantes e,matriculas m WHERE (t.descripcion like '%s' OR t.descripcion like '%s')AND tc.idtransaccion=t.id AND ti.id=tc.idcuenta AND t.idestado=1 AND tc.idestado=1 AND ti.oficial>2705451900000 AND ti.oficial<2705459000000 AND ti.oficial-2705450000000=e.codigoestudiante::bigint AND m.estudiante=e.id AND m.periodo=%d GROUP BY e.codigoestudiante,m.costopension HAVING SUM(tc.valor*tc.signo)<0" % ("%:["+str(anio)+"-A%","%:["+str(anio)+"-a%",anio)
plpy.info(q3)
res=plpy.execute(q3)
"""
a
27
      13
"""
for i in res :
  plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES ('%s:[%d-a%d] Se cancela pago anticipado %s estudiante %s',date('01/%d/%d'),(SELECT id FROM periodoscontables WHERE date_le(fechaini,date('01/%d/%d')) AND date_le(date('01/%d/%d'),fechafin)),1,date('today'),1,(SELECT id FROM estudiantes WHERE codigoestudiante='%s'),%d,%d,%d)" % (i["codigoestudiante"],anio,periodo,meses[periodo-1],i["codigoestudiante"],periodo+1,anio,periodo+1,anio,periodo+1,anio,i["codigoestudiante"],usuario,tiponota,nronotai))
  id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like '%s:[%d-a%d]%s'" % (i["codigoestudiante"],anio,periodo," Se cancela pago anticipado %"))[0]["id"]
  #Se asume que el valor pagado anticipado es inferior a lo que tendría que cancelar en el mes.
  cadena="270545,%s,%f,0|130505,%s,0,%f" % (i["codigoestudiante"],i["adelanto"],i["codigoestudiante"],i["adelanto"])
  if i["adelanto"] > i["costopension"] :
    #En caso de que el adelanto sea mayor que el costo de la pensión del mes, se descuenta 
    #solamente la pensión.
    cadena="270545,%s,%f,0|130505,%s,0,%f" % (i["codigoestudiante"],i["costopension"],i["codigoestudiante"],i["costopension"])
  cant=cant+plpy.execute("SELECT registratransacciones('%s',%d)" % (cadena,id))[0]["registratransacciones"]

return cant+len(res)
$$
LANGUAGE plpythonu;


-- Registra una transacción indicando que hizo el pago del estudiante cancelando
-- la subcuenta por cobrar específica que debía haber sido causada con anterioridad
-- y también registrando en la cuenta de bancos
-- Recibe una cadena con la fecha en la cuál aparecería realizada la transacción, 
-- el año, el mes(1 es Febrero, 10 es Noviembre), el valor del pago que hizo,
-- el código del estudiante, una descripción adicional, el id de quien registra
-- la transacción y el número de consignación
-- Retorna la cantidad de registros adicionados : 3
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION pagopension(text,int4,int4,numeric,text,text,int4,int4,text) RETURNS int
AS
'
meses=["Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre"]
fecha=args[0]
anio=args[1]
periodo=args[2]
valor=args[3]
codigoestudiante=args[4]
descripcion=args[5]
idregistra=args[6]
nroconsigna=args[7]
banco=args[8]
tipoc=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''CO''")[0]["id"]
res=0
myins="SELECT registratransaccion(1,id,date(''%s''),date(''now''),''%s:[%d-P%d] Pagando mes(es) %s estudiante %s %s''::text,%d,1,''%s,,%s,0|130505,%s,0,%s''::text,%d,%d) FROM estudiantes WHERE codigoestudiante=%s::text" % (fecha,codigoestudiante,anio,periodo,meses[periodo-1],codigoestudiante,descripcion,idregistra,banco,valor,codigoestudiante,valor,nroconsigna,tipoc,codigoestudiante)
res=plpy.execute(myins)[0]["registratransaccion"]
return res+1	
'
LANGUAGE plpythonu;

-- Se adiciona descuento a la tabla de descuentos en Pensiones.
-- Recibe el id de la persona, el año en el cuál se aplica el descuento,
-- la descripción de por qué se hace el descuento, la fecha en que comienza
-- a aplicarse el descuento y la fecha en que finaliza.  
-- Recibe las fechas como cadenas de caracteres, usualmente serían :
-- 01/01/anio 30/11/anio
-- Si ya existía un registro, no adiciona el descuento.
-- Si no existía la subcuenta de descuento, es creada.
-- Retorna la cantidad de registros adicionados : 0, 1 o 2
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION creardescuento(int4,int4,text,numeric,numeric,text,text) RETURNS int
AS
'
id=args[0]
anio=args[1]
descripcion=args[2]
pago=args[3]
descuento=args[4]
fi=args[5]
ff=args[6]
if plpy.execute("SELECT count(*) FROM descuentos WHERE persona=%d AND periodo=%d" % (id,anio))[0]["count"]>0 :
  return 0
res=plpy.execute("INSERT INTO descuentos (persona,periodo,concepto,pago,descuento,fechainicial,fechafinal) VALUES (%d,%d,(SELECT codigoestudiante||''[%d-P] %s'' FROM estudiantes WHERE id=%d),%s,%s,date(''%s''),date(''%s'')) " %(id,anio,anio,descripcion,id,pago,descuento,fi,ff))
if plpy.execute("SELECT COUNT(*) FROM tiposcuenta WHERE oficial=4175010000000+int8((SELECT codigoestudiante FROM estudiantes WHERE id=%d))" % id)[0]["count"]==0 :
  #Si la subcuenta de descuentos para el estudiante no existía, se crea.
  plpy.execute("INSERT INTO tiposcuenta(oficial,descripcion,hijade,naturaleza,puc) VALUES (4175010000000+int8((SELECT codigoestudiante FROM estudiantes WHERE id=%d)),''Descuentos en costos educativos ''||(SELECT codigoestudiante FROM estudiantes WHERE id=%d),(SELECT id FROM tiposcuenta WHERE oficial=417501),-1,0)" %(id,id))
  return 2
return 1
'
LANGUAGE plpythonu;

-- Registra una transacción indicando que hizo el pago del estudiante con descuento,
-- cancelando la subcuenta por cobrar específica que debía haber sido causada con 
-- anterioridad, la subcuenta de descuentos y también registrando en la cuenta de
--  bancos
-- Recibe una cadena con la fecha en la cuál aparecería realizada la transacción, 
-- el año, el mes(1 es Febrero, 10 es Noviembre), el valor del pago que hizo,
-- el código del estudiante, una descripción adicional, el id de quien registra
-- la transacción y el número de consignación
-- El descuento se calcula automáticamente sumando todos los descuentos aplicables 
-- a la fecha del pago.
-- Retorna la cantidad de registros adicionados : 4, en caso de que la persona no
-- tenga registro en la tabla de descuentos, no adicionará nada y retornará 0.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION pagopensiondto(text,int4,int4,numeric,text,text,int4,int4,text) RETURNS int
AS
'
meses=["Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre"]
fecha=args[0]
anio=args[1]
periodo=args[2]
valor=args[3]
codigoestudiante=args[4]
descripcion=args[5]
idregistra=args[6]
nroconsigna=args[7]
banco=args[8]
tipoc=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''CO''")[0]["id"]
cant=0
res=plpy.execute("SELECT sum(d.descuento) AS descuento FROM descuentos d,estudiantes e WHERE e.id=d.persona AND e.codigoestudiante=%s AND d.periodo=%d AND d.concepto LIKE ''%s[%d-P]%s''" % (codigoestudiante,anio,codigoestudiante,anio,"%"))
if len(res)==0 or res[0]["descuento"]==None:
  #Si no tenía descuento, no puede adicionar nada.
  return cant
descuento=res[0]["descuento"]
plpy.info("SELECT registratransacciones(''%s,,%s,0|417501,%s,%s,0|130505,%s,0,%f'',%d)" % (banco,valor,codigoestudiante,descuento,codigoestudiante,valor+descuento,3))
return 0
plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES (''%s:[%d-P%d] Pagando mes(es) %s con descuento estudiante %s %s'',date(''%s''),(SELECT id FROM periodoscontables WHERE date_le(fechaini,date(''%s'')) AND date_le(date(''%s''),fechafin)),1,date(''today''),1,(SELECT id FROM estudiantes WHERE codigoestudiante=%s),%d,%d,%d)" % (codigoestudiante,anio,periodo,meses[periodo-1],codigoestudiante,descripcion,fecha,fecha,fecha,codigoestudiante,idregistra,tipoc,nroconsigna))
id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like ''%s:[%d-P%d]%s''" % (codigoestudiante,anio,periodo," Pagando mes(es) %"))[0]["id"]
cant=cant+plpy.execute("SELECT registratransacciones(''%s,,%s,0|417501,%s,%s,0|130505,%s,0,%f'',%d)" % (banco,valor,codigoestudiante,descuento,codigoestudiante,valor+descuento,id))[0]["registratransacciones"]
return cant+1	
'
LANGUAGE plpythonu;


-- Registra una transacción indicando que hizo el pago del estudiante con descuento,
-- y por anticipado abonando en las subcuentas de descuentos y pagos recibidos por
-- anticipado para el estudiante y registrando en la cuenta de bancos
-- Recibe una cadena con la fecha en la cuál aparecería realizada la transacción, 
-- el año, el mes(1 es Febrero, 10 es Noviembre), el valor del pago que hizo,
-- el código del estudiante, una descripción adicional, el id de quien registra
-- la transacción y el número de consignación
-- El descuento se calcula automáticamente sumando todos los descuentos aplicables 
-- a la fecha del pago.
-- Retorna la cantidad de registros adicionados : 4, en caso de que la persona no
-- tenga registro en la tabla de descuentos, no adicionará registros y retornará 0.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION pagoanticipadodto(text,int4,int4,numeric,text,text,int4,int4,text) RETURNS int
AS
'
meses=["Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre"]
fecha=args[0]
anio=args[1]
periodo=args[2]
valor=args[3]
codigoestudiante=args[4]
descripcion=args[5]
idregistra=args[6]
nroconsigna=args[7]
banco=args[8]
tipoc=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''CO''")[0]["id"]
cant=0
res=plpy.execute("SELECT sum(d.descuento) AS descuento FROM descuentos d,estudiantes e WHERE e.id=d.persona AND e.codigoestudiante=%s AND d.periodo=%d AND d.concepto LIKE ''%s[%d-P]%s''" % (codigoestudiante,anio,codigoestudiante,anio,"%"))
if len(res)==0 :
  #Si no tenía descuento, no puede adicionar nada.
  return cant
descuento=res[0]["descuento"]
plpy.execute("INSERT INTO transacciones(descripcion,fecha,idperiodo,idestado,fecharegistro,tipotercero,idtercero,idusuario,idtipocomprobante,idcomprobante) VALUES (''%s:[%d-A%d] Pago anticipado con descuento mes(es) %s estudiante %s %s'',date(''%s''),(SELECT id FROM periodoscontables WHERE date_le(fechaini,date(''%s'')) AND date_le(date(''%s''),fechafin)),1,date(''today''),1,(SELECT id FROM estudiantes WHERE codigoestudiante=%s),%d,%d,%d)" % (codigoestudiante,anio,periodo,meses[periodo-1],codigoestudiante,descripcion,fecha,fecha,fecha,codigoestudiante,idregistra,tipoc,nroconsigna))
id=plpy.execute("SELECT id FROM transacciones WHERE descripcion like ''%s:[%d-A%d]%s''" % (codigoestudiante,anio,periodo," Pago anticipado con descuento mes(es) %"))[0]["id"]
cant=cant+plpy.execute("SELECT registratransacciones(''%s,,%s,0|417501,%s,%s,0|270545,%s,0,%f'',%d)" % (banco,valor,codigoestudiante,descuento,codigoestudiante,valor+descuento,id))[0]["registratransacciones"]
return cant+1	
'
LANGUAGE plpythonu;

-- Recibe el año para el período en el cuál se desea crear las vistas
-- Ejemplo de uso :
-- SELECT creavistas(2005);
-- Crearía las vistas para el año 2005 : 
-- * cartera2005 : Estudiantes con cartera morosa para el 2005
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION creavistas(int4) RETURNS int
AS $$
#Esta vista espera que en 270545 esté acumulados los pagos hechos por anticipado, que 130505 lleve cuenta de las deudas contraídas con la institución.
anio=args[0]
query="CREATE OR REPLACE VIEW cartera%d AS SELECT t.idtercero AS id,nombre(t.idtercero) AS estudiante,sum(tc.valor*tc.signo) AS debe, round(SUM(tc.valor*tc.signo)/m.costopension,1) AS meses,c.nombre AS curso,e.codigoestudiante AS codigo FROM estudiantes e,matriculas m,tiposcuenta ti,transacciones t,transaccionescuenta tc, cursos c where t.descripcion SIMILAR TO '%s' AND t.id=tc.idtransaccion AND t.idestado=1 AND tc.idestado=1 AND ti.id=tc.idcuenta AND (ti.oficial LIKE '%s' OR ti.oficial LIKE '%s') AND m.periodo=%d AND m.estudiante=t.idtercero AND m.curso=c.id AND e.id=m.estudiante GROUP BY t.idtercero,m.costopension,c.nombre,e.codigoestudiante;" %(anio,"%:\\\\\\["+str(anio)+"-(C|A|P)%","130505%","270545%",anio)
plpy.execute(query)
query="CREATE OR REPLACE VIEW matriculados%s AS SELECT t.id AS idtransaccion,nombre(s.idestudiante) AS estudiante,s.curso,t.idcomprobante,s.costopension,nombre(t.idusuario) AS registra,t.fecharegistro,sum(tc.valor) AS consignado FROM transaccionescuenta tc,(SELECT todos.idestudiante, todos.fechamatricula, todos.ordencurso, todos.curso, todos.costopension, todos.fecharetiro FROM (SELECT m.estudiante AS idestudiante, m.fecha AS fechamatricula, c.orden AS ordencurso, c.nombre AS curso, m.costopension, '31/12/%s'::date AS fecharetiro FROM matriculas m, cursos c WHERE ((((c.id = m.curso) AND (m.activo = true)) AND (m.periodo = %s)) AND (m.periodo = c.periodo)) UNION SELECT m.estudiante, m.fecha, c.orden, c.nombre, m.costopension, r.fechasalida FROM matriculas m, cursos c, retiros r WHERE ((((((c.id = m.curso) AND (m.activo = false)) AND (r.id = m.estudiante)) AND (r.periodo = m.periodo)) AND (m.periodo = %s)) AND (m.periodo = c.periodo))) todos) AS s, transacciones t, datospersonales d WHERE t.descripcion like '%s' AND t.idtercero=s.idestudiante AND d.id=t.idtercero and tc.idtransaccion=t.id AND tc.signo=1 GROUP BY s.fechamatricula,s.idestudiante,s.ordencurso,s.curso,s.costopension,t.id,t.idusuario,t.fecharegistro,d.apellido1,d.apellido2,d.nombres,t.idcomprobante ORDER BY s.ordencurso,s.curso,d.apellido1,d.apellido2,d.nombres;" % (anio,anio,anio,anio,'%'+str(anio)+'-M%')
plpy.execute(query);
$$
LANGUAGE plpythonu;


-- Recibe el id del estudiante, el período(año), la fecha de retiro y el id
-- de la persona que registra
-- Ejemplo de uso :
-- SELECT retirarestudiante(350,2006,'30/05/2006',13);
-- Retiraría al estudiante con id 350 en el período 2006 con fecha de 30 de
-- Mayo de 2006 registrado por el usuario con id 13.  Se modifica la tabla
-- matriculas, se adiciona a la tabla retiros y se adiciona a logstransaccion
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION retirarestudiante(int4,int4,text,int4) RETURNS int
AS '
idest=args[0]
anio=args[1]
fecha=args[2]
registra=args[3]
q="INSERT INTO retiros(id,periodo,fechaingreso,fechasalida) SELECT estudiante,periodo,fecha,date(''%s'') from matriculas where estudiante=%d and periodo=%d" % (fecha,idest,anio)
plpy.execute(q)
q1="UPDATE matriculas SET activo=false WHERE estudiante=%d AND periodo=%d" % (idest,anio)
plpy.execute(q1)
q2="INSERT INTO logstransaccion(referencia,fecha,tipotransaccion,registra,detalle) SELECT %d,date(''now''),id,%d,''Retiro %s'' FROM tiposlogtransaccion where nombre=''Retiro estudiante''" % (idest,registra,fecha) 
plpy.execute(q2)
return 3
' LANGUAGE plpythonu; 

-- Recibe el id de la transaccion, el id de quien va hace el retiro de la
-- trans., adicionalmente recibe el comentario por el cual se remueve la
-- transaccion
-- Ejemplo de uso :
-- SELECT eliminartransaccion(28315,27,'Tiene registro en ceros');
-- Elmina la trans. con id 28315, dejando al usuario 27 como responsable
-- de eliminar la trans. y con el comentario...
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION eliminartransaccion(int4,int4,text) RETURNS int
AS '
idt=args[0]
reg=args[1]
motivo=args[2]

q0="SELECT pc.idestado FROM periodoscontables pc, transacciones t WHERE t.id=%d AND pc.id=t.idperiodo AND pc.idestado=1" % (idt)
res=plpy.execute(q0)
if len(res)!=1:
  #Se verifica que trate de eliminar una trans. de un periodo abierto.
  return -1
q="UPDATE transaccionescuenta set idestado=2 where idtransaccion=%d" % (idt)
res=plpy.execute(q)
cant=len(res)
q1="UPDATE transacciones SET idestado=2 WHERE id=%d" % (idt)
res=plpy.execute(q1)
cant=cant+len(res)+1
q2="INSERT INTO logstransaccion(referencia,fecha,tipotransaccion,registra,detalle) SELECT %d,date(''now''),id,%d,''Elimina trans. %s'' FROM tiposlogtransaccion where nombre=''Eliminar RegTrans''" % (idt,reg,motivo) 
plpy.execute(q2)
return cant
' LANGUAGE plpythonu; 

-- Recibe logins de dos estudiantes del colegio y el año
-- Ejemplo de uso :
-- SELECT hacerhermanos('carpae','joapae',2006);
-- Clona la información de padres y acudientes del estudiante 'carpae' en 'joapae', 
-- si el segundo tiene datos, no se hace la clonación.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd
CREATE OR REPLACE FUNCTION hacerhermanos(text,text,int) RETURNS int
AS '
orig=args[0]
otro=args[1]
anio=args[2]

#Se actualiza la dirección
q="SELECT d.direccioncasa FROM datospersonales d, estudiantes e  WHERE e.id=d.id AND e.login=''%s'' AND d.direccioncasa is not null" % (otro)

res=plpy.execute(q)
cant=len(res)
if cant>=1:
  #Se actualizan datos de dirección en el hermano si no tenía.
  q="UPDATE datospersonales SET direccioncasa = n.direccioncasa FROM (select d.direccioncasa from datospersonales d, estudiantes e where e.id=d.id AND e.login=''%s'') AS n,estudiantes e WHERE datospersonales.id=e.id AND e.login=''%s''" % (orig,otro)
  plpy.execute(q)
  
q="SELECT e.madre, e.padre, m.acudiente1, m.acudiente2 FROM estudiantes e, matriculas m WHERE e.login=''%s'' AND m.estudiante=e.id AND m.periodo=%d" % (otro,anio)
res=plpy.execute(q)
cant=len(res)
if cant!=1 :
  #Se verifica que exista el segundo login
  return 0

#Se verifica que todos los datos en el segundo sean nulos
for i in res[0].itervalues():
  if i!=None:
    return 0

q="UPDATE estudiantes SET madre=orig.madre, padre=orig.padre FROM (SELECT e.madre, e.padre, m.acudiente1, m.acudiente2 FROM estudiantes e, matriculas m WHERE e.login=''%s'' AND m.estudiante=e.id AND m.periodo=%d) AS orig WHERE login=''%s''" % (orig,anio,otro)
plpy.execute(q)

q="UPDATE matriculas SET acudiente1=orig.acudiente1, acudiente2=orig.acudiente2 FROM (SELECT e.madre, e.padre, m.acudiente1, m.acudiente2,e.id FROM estudiantes e, matriculas m WHERE e.login=''%s'' AND m.estudiante=e.id AND m.periodo=%d) AS orig, estudiantes e2 WHERE e2.id=estudiante AND periodo=%d AND e2.login=''%s''" % (orig,anio,anio,otro)
plpy.execute(q)
return 1
' LANGUAGE plpythonu; 

-- Recibe el id de la transacción a modificar, el año y cambia la cuenta de la 13 a la
-- 27.
-- Ejemplo :
--    select saldodecuenta(2007,33692);
-- Modificaría la transacción 33692 en el período 2007 verificando si es un pago previo
-- registrado como Pago posterior, modificando los registros de la causación para
-- saldar el pago previo.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpythonu bd

CREATE OR REPLACE FUNCTION arreglapagopreviocausado(int4,int4) RETURNS numeric
AS '
anio=args[0]
idt=args[1]
#Se busca la
q="SELECT t.id,busca.per,busca.previo,busca.anio FROM transacciones t, (SELECT substring (descripcion,0,15) AS inicial,substring(descripcion, ''%d-P([0-9])'') AS per ,int4(to_char(fecha,''MM''))-int4(substring(descripcion, ''%d-P([0-9])'')) AS previo,%d-int4(to_char(fecha,''YYYY'')) as anio FROM transacciones WHERE id=%d AND idestado=1) AS busca WHERE descripcion LIKE (busca.inicial||''C''||busca.per||''%s'') and t.idestado=1" %(anio, anio, anio, idt , ''%'')
res1=plpy.execute(q)
if len(res1)>0 :
  if res1[0]["previo"]<=0 and res1[0]["anio"]>=0:
    #La transacción se cambia si es de pago y se hizo en una fecha previa a la causación.
    idn=res1[0]["id"]
    #Se busca los ids de trece y veintisiete dada la transacción
    q="SELECT sub.idcuenta AS tr, ti.id  as vs FROM (SELECT tc.idcuenta,''270545''||substr(ti.oficial,7) AS vs FROM transaccionescuenta tc, tiposcuenta ti WHERE tc.idtransaccion=%d AND tc.idcuenta=ti.id AND ti.oficial LIKE ''130505%s'') AS sub , tiposcuenta ti WHERE ti.oficial=sub.vs" % (idt,"%")
    res2=plpy.execute(q)
    if len(res2)<1:
      #Debería existir las dos cuentas : 13 y 27 para el estudiante de la transacción.
      return 0
    tr=res2[0]["tr"]
    vs=res2[0]["vs"]
    #Se cambia la descripción de las transacciones
    q="UPDATE transacciones set descripcion=replace(replace(descripcion , ''Pagando'' , ''Pago anticipado''),''%d-P'',''%d-A'') WHERE id=%d" %(anio,anio,idt);
    plpy.execute(q)
    q="UPDATE transacciones set descripcion=replace(replace(descripcion , ''Causando mes'' , ''Se cancela pago anticipado''),''%d-C'',''%d-a'') WHERE id=32179" %(anio,anio);
    plpy.execute(q)
    #Se cambia las subcuentas de las transacciones
    q="UPDATE transaccionescuenta set idcuenta=%d WHERE idcuenta=%d AND (idtransaccion=%d OR idtransaccion=%d)" % (vs,tr,idt,idn)
    plpy.execute(q)
return 4
'
LANGUAGE plpythonu;

-- Recibe el codigo del estudiante, el valor de la transaccion, el id del comprobante,
-- la fecha a aplicar, el tipo de ajuste + o -, el id de quien registra y el periodo de
-- la transaccion.
-- se usa cuando un estudiante es causado por mayor valor o hay que cobrar un saldo mayor
-- Incluye como P0 la transacciOn en una nota interna usualmente, el modo de uso serIa:
-- SELECT ajusteingresoestudiante('1999004',20800,183,'15/11/2008'::text,'+',13);
-- Que haria un ajuste por $20800 para el estudiante a favor del colegio con el ajuste 183
-- en la fecha del 15 de nov. de 2008.

CREATE OR REPLACE FUNCTION ajusteingresoestudiante(text,float,int4,text,text,int4,int4) RETURNS int AS
'
codigo=args[0]
valor=args[1]
idcom=args[2]
fecha=args[3]
tipo=args[4]
idregistra=args[5]
anio=args[6]
idest=plpy.execute("SELECT id FROM estudiantes WHERE codigoestudiante=''%s'' LIMIT 1" % codigo)[0]["id"]
if tipo==''+'':
    #Deuda de mayor valor a favor del colegio
    cuentas="''130505,%s,%f,0|416005,%s,0,%f''" % (codigo,valor,codigo,valor)
else:
    #Deuda de menor valor a favor del colegio
    cuentas="''417501,%s,%f,0|130505,%s,0,%f''" % (codigo,valor,codigo,valor)
theval="SELECT registratransaccion(1,%d,''%s''::text,''today''::text,''%s:[%d-P0] Pagando estudiante %s Ajuste pagos''::text,%d,1,%s,%d,4)" % (idest,fecha,codigo,anio,codigo,idregistra,cuentas,idcom)
cant=plpy.execute(theval)[0]["registratransaccion"]
return cant
'
LANGUAGE plpythonu;



-- Recibe el id de datospersonales para eliminar y el id de la persona
-- que está eliminando los datospersonales.
-- Se eliminan datos de las tablas transaccionescuenta, transacciones,
-- tiposcuenta, admisiones, matriculas, estudiantes y datospersonales
-- Ejemplo de uso :
-- SELECT destrozapersona(780,3);
-- Eliminará a la persona 780 adjudicando esta acción a 3.
-- Requiere que se haya creado el lenguaje previamente para la base de datos
-- /usr/lib/postgresql/createlang plpgsql bd
CREATE OR REPLACE FUNCTION destrozapersona(idper INT,quien int) RETURNS integer AS
$$
BEGIN
INSERT INTO logstransaccion(referencia,fecha,tipotransaccion,registra,detalle) SELECT idper,date('now'),l.id,quien,nombre(idper) FROM tiposlogtransaccion  l where l.nombre='Destruir Datos Personales';
DELETE FROM transaccionescuenta USING transacciones t WHERE t.idtercero=idper AND transaccionescuenta.idtransaccion=t.id;
DELETE FROM tiposcuenta USING estudiantes e WHERE tiposcuenta.oficial like '%'||e.codigoestudiante AND e.id=idper AND length(tiposcuenta.oficial||'')>10;
DELETE FROM transacciones WHERE idtercero=idper and tipotercero=1;
DELETE FROM admisiones WHERE persona =idper;
DELETE FROM matriculas WHERE estudiante =idper;
DELETE FROM estudiantes WHERE id=idper;
DELETE FROM datospersonales WHERE id=idper;
return 1;
END;
$$
LANGUAGE plpgsql;


-- Recibe la cuenta cuyas subcuentas van a ser canceladas, la cuenta
-- en la cual se va a colocar el saldo de la cancelación de subcuentas,
-- el año para el cual se va a hacer la cancelación
-- el id del tercero al cual va a quedar asignada la transacción
-- el id del usuario que efectuó la operación
-- SELECT reclasifica('130505','130505',2010,13);
CREATE OR REPLACE FUNCTION reclasifica(text,text,int4,int4,int4) RETURNS integer AS
'
padre=args[0]
contra=args[1]
anio=args[2]
idtercero=args[3]
idusuario=args[4]
try:
  psaldos=plpy.execute("SELECT id FROM periodoscontables WHERE nombre=''Cancela %d''" %(anio-1))[0]["id"]
except:
  #No existIa el año en cuestión para hacer la reclasificacion
  return -2
pfinal=plpy.execute("SELECT id FROM periodoscontables WHERE nombre=''Cancela %d''" %anio)[0]["id"]
try:
  res=plpy.execute("SELECT id,naturaleza FROM tiposcuenta WHERE oficial=''%s''" % contra)
  idcontra=res[0]["id"]
  natcontra=res[0]["naturaleza"]
except:
  #No existIa la cuenta de contrapartida
  return -1
try:
  res=plpy.execute("SELECT id,fechaini FROM periodoscontables WHERE nombre=''Diciembre %d''" % anio)
  idperiodo=res[0]["id"]
  fecha=res[0]["fechaini"]
except:
  #No existía Diciembre del período en el que se colocará la reclasificación de cuentas
  return -3
#Búsqueda del id de la transaccion
nronotai=1+plpy.execute("SELECT ultimatransaccion(id) from tiposcomprobante where abrevia=''NI''")[0]["ultimatransaccion"]
tiponota=plpy.execute("SELECT id FROM tiposcomprobante WHERE abrevia=''NI''")[0]["id"]
plpy.execute("INSERT INTO transacciones(idcomprobante,fecha,descripcion,tipotercero,idtercero,idestado,idusuario,fecharegistro,idperiodo,idtipocomprobante) VALUES (%d,''%d-12-30'',''Reclasificación de subcuentas de %s frente a %s en %d'',%d, %d,%d,%d,date(''now''),%d,%d)" % (nronotai,anio,padre,contra,anio,4,idtercero,1,idusuario,idperiodo,tiponota))
try:
  idtrans=plpy.execute("SELECT max(id) from transacciones WHERE idtipocomprobante=%d AND descripcion=''Reclasificación de subcuentas de %s frente a %s en %d''" % (tiponota,padre,contra,anio))[0]["max"]
except:
  #No se hizo la inserción de la transacción
  return -4

q="SELECT coalesce(sal.id,mov.id) AS id, coalesce(sal.oficial,mov.oficial) AS cuenta, coalesce(sal.naturaleza,mov.naturaleza,1) AS nat,coalesce(sal.inicial,0) AS ini,coalesce(mov.per,0) AS movi, coalesce(sal.inicial,0)+coalesce(mov.per,0)*coalesce(sal.naturaleza,mov.naturaleza,1) AS fin FROM (SELECT ti.id,ti.naturaleza, ti.oficial,(sum(s.debito)-sum(s.credito))*ti.naturaleza AS inicial FROM saldos s, tiposcuenta ti WHERE s.idtiposcuenta= ti.id AND s.idperiodo=%(psaldos)d AND text(ti.oficial) like ''%(padre)s'' AND char_length(text(ti.oficial))>char_length(''%(padre)s'') GROUP BY ti.oficial, ti.naturaleza , ti.descripcion,ti.id ORDER BY ti.oficial) AS sal FULL OUTER JOIN (SELECT ti.id,ti.naturaleza,ti.oficial , SUM(tc.valor*tc.signo) AS per FROM tiposcuenta ti, transaccionescuenta tc , transacciones t WHERE t.idestado=1 AND tc.idestado=1 AND ti.id=tc.idcuenta  AND t.id=tc.idtransaccion AND t.idperiodo>%(psaldos)d AND t.idperiodo<%(pfinal)d AND text(ti.oficial) LIKE ''%(padre)s'' AND char_length(text(ti.oficial))>char_length(''%(padre)s'') GROUP BY ti.oficial,ti.id,ti.naturaleza ORDER BY ti.oficial) AS mov ON sal.oficial=mov.oficial"
res=plpy.execute(q % {"psaldos":psaldos , "pfinal":pfinal , "padre":padre+"%"})
trans=""
regs=1
saldo=0.0
for i in res :
  if i["fin"]!=0:
    saldo+=i["fin"]*i["nat"]
    if i["fin"]*i["nat"]<0:
      trans="%s,,%d,0" % (i["cuenta"],abs(i["fin"]))
    else:
      trans="%s,,0,%d" % (i["cuenta"],abs(i["fin"]))
    plpy.execute("SELECT registratransacciones(''%s'',%d);" % (trans,idtrans))
    regs+=1
if saldo>0:
   trans="%s,,%d,0" %(contra,abs(saldo))
else:
   trans="%s,,0,%d" % (contra,abs(saldo))
plpy.execute("SELECT registratransacciones(''%s'',%d);" % (trans,idtrans))
return regs
'
LANGUAGE plpythonu;


COMMIT;