ZahirJS commited on
Commit
cf59592
·
verified ·
1 Parent(s): 505ff60

Update entity_relationship_generator.py

Browse files
Files changed (1) hide show
  1. entity_relationship_generator.py +79 -129
entity_relationship_generator.py CHANGED
@@ -332,27 +332,12 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
332
  {"name": "nombre_depto", "type": "regular"}
333
  ]
334
  },
335
- {
336
- "name": "TECNICO",
337
- "type": "strong",
338
- "attributes": [
339
- {"name": "nivel", "type": "regular"}
340
- ]
341
- },
342
- {
343
- "name": "ADMINISTRATIVO",
344
- "type": "strong",
345
- "attributes": []
346
- },
347
  {
348
  "name": "PROYECTO",
349
  "type": "strong",
350
  "attributes": [
351
  {"name": "cod_proyecto", "type": "primary_key"},
352
- {"name": "nombre_proyecto", "type": "regular"},
353
- {"name": "cliente", "type": "regular"},
354
- {"name": "fecha_inicio", "type": "regular"},
355
- {"name": "fecha_fin", "type": "regular"}
356
  ]
357
  }
358
  ],
@@ -364,24 +349,14 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
364
  "cardinalities": {
365
  "EMPLEADO": "N",
366
  "DEPARTAMENTO": "1"
367
- },
368
- "attributes": [
369
- {"name": "fecha_asignacion", "type": "regular"},
370
- {"name": "fecha_cese", "type": "regular"}
371
- ]
372
- },
373
- {
374
- "name": "Es_un",
375
- "type": "isa",
376
- "parent": "EMPLEADO",
377
- "children": ["TECNICO", "ADMINISTRATIVO"]
378
  },
379
  {
380
  "name": "Trabaja_en",
381
  "type": "regular",
382
- "entities": ["TECNICO", "PROYECTO"],
383
  "cardinalities": {
384
- "TECNICO": "M",
385
  "PROYECTO": "N"
386
  }
387
  }
@@ -400,25 +375,16 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
400
  if 'entities' not in data:
401
  raise ValueError("Missing required field: entities")
402
 
403
- # Crear grafo con estilo mejorado
404
  dot = graphviz.Graph(comment='ER Diagram', engine='dot')
405
- dot.attr(
406
- rankdir='TB',
407
- bgcolor='white',
408
- pad='0.8',
409
- nodesep='1.2',
410
- ranksep='1.8',
411
- fontname='Arial'
412
- )
413
-
414
- # Configuración base de nodos y aristas
415
- dot.attr('node', fontname='Arial', fontsize='11', color='#404040')
416
- dot.attr('edge', fontname='Arial', fontsize='10', color='#404040')
417
 
418
  entities = data.get('entities', [])
419
  relationships = data.get('relationships', [])
420
 
421
- # Crear entidades con estilo profesional
422
  for entity in entities:
423
  entity_name = entity.get('name')
424
  entity_type = entity.get('type', 'strong')
@@ -427,21 +393,26 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
427
  continue
428
 
429
  if entity_type == 'weak':
430
- # Entidad débil: doble rectángulo (simulado con tabla HTML)
431
- label = f'<<TABLE BORDER="3" CELLBORDER="1" CELLSPACING="0" CELLPADDING="8" BGCOLOR="#f0f0f0"><TR><TD><B>{entity_name}</B></TD></TR></TABLE>>'
432
- dot.node(entity_name, label, shape='plaintext')
 
 
 
 
 
 
 
433
  else:
434
- # Entidad fuerte: rectángulo simple con estilo
435
  dot.node(
436
  entity_name,
437
  entity_name,
438
  shape='box',
439
- style='filled,rounded',
440
  fillcolor='#e8e8e8',
441
  color='#404040',
442
- penwidth='2',
443
- fontsize='12',
444
- fontcolor='#000000'
445
  )
446
 
447
  # Crear atributos para cada entidad
@@ -459,45 +430,41 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
459
  # Clave primaria: elipse con texto subrayado
460
  dot.node(
461
  attr_id,
462
- f'<U><B>{attr_name}</B></U>',
463
  shape='ellipse',
464
  style='filled',
465
- fillcolor='#d0d0d0',
466
  color='#404040',
467
- penwidth='2'
468
  )
469
  elif attr_type == 'partial_key':
470
- # Clave parcial: elipse con línea punteada
471
  dot.node(
472
  attr_id,
473
- f'<U>{attr_name}</U>',
474
  shape='ellipse',
475
  style='filled,dashed',
476
- fillcolor='#d0d0d0',
477
- color='#404040',
478
- penwidth='2'
479
  )
480
  elif attr_type == 'multivalued':
481
- # Atributo multivaluado: doble elipse (tabla HTML)
482
- label = f'<<TABLE BORDER="2" CELLBORDER="0" CELLSPACING="0" CELLPADDING="4" BGCOLOR="#d8d8d8"><TR><TD>{attr_name}</TD></TR></TABLE>>'
483
- dot.node(attr_id, label, shape='plaintext')
484
- elif attr_type == 'derived':
485
- # Atributo derivado: elipse con línea punteada
486
  dot.node(
487
  attr_id,
488
- f'/{attr_name}/',
489
  shape='ellipse',
490
- style='filled,dashed',
491
  fillcolor='#d8d8d8',
492
- color='#404040'
 
493
  )
494
- elif attr_type == 'composite':
495
- # Atributo compuesto
496
  dot.node(
497
  attr_id,
498
- attr_name,
499
  shape='ellipse',
500
- style='filled',
501
  fillcolor='#d8d8d8',
502
  color='#404040'
503
  )
@@ -513,12 +480,18 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
513
  )
514
 
515
  # Conectar atributo con entidad
516
- dot.edge(entity_name, attr_id, color='#404040', penwidth='1')
517
 
518
  # Crear relaciones
519
  for relationship in relationships:
520
  rel_name = relationship.get('name')
521
  rel_type = relationship.get('type', 'regular')
 
 
 
 
 
 
522
 
523
  if rel_type == 'isa':
524
  # Relación ISA (jerarquía)
@@ -526,53 +499,52 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
526
  children = relationship.get('children', [])
527
 
528
  if parent and children:
529
- # Crear nodo ISA como triángulo
530
- isa_id = f"isa_{rel_name}"
531
  dot.node(
532
- isa_id,
533
  'ISA',
534
  shape='triangle',
535
  style='filled',
536
- fillcolor='#c0c0c0',
537
- color='#404040',
538
- penwidth='2'
539
  )
540
 
541
  # Conectar padre con ISA
542
- dot.edge(parent, isa_id, color='#404040', penwidth='2')
543
 
544
  # Conectar ISA con hijos
545
  for child in children:
546
- dot.edge(isa_id, child, color='#404040', penwidth='2')
547
 
548
- else:
549
- # Relación regular
550
- entities_involved = relationship.get('entities', [])
551
- cardinalities = relationship.get('cardinalities', {})
552
- rel_attributes = relationship.get('attributes', [])
553
-
554
- if not rel_name or len(entities_involved) < 2:
555
- continue
 
 
 
556
 
557
- rel_type_style = relationship.get('type', 'regular')
 
 
 
558
 
559
- if rel_type_style == 'identifying':
560
- # Relación identificadora: doble rombo
561
- label = f'<<TABLE BORDER="3" CELLBORDER="0" CELLSPACING="0" CELLPADDING="6" BGCOLOR="#c8c8c8"><TR><TD><B>{rel_name}</B></TD></TR></TABLE>>'
562
- dot.node(rel_name, label, shape='plaintext')
563
- else:
564
- # Relación regular: rombo simple
565
- dot.node(
566
- rel_name,
567
- rel_name,
568
- shape='diamond',
569
- style='filled',
570
- fillcolor='#c8c8c8',
571
- color='#404040',
572
- penwidth='2'
573
- )
574
 
575
- # Crear atributos de la relación
576
  for i, attr in enumerate(rel_attributes):
577
  attr_name = attr.get('name', '')
578
  attr_id = f"{rel_name}_attr_{i}"
@@ -590,29 +562,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
590
  # Conectar entidades con la relación
591
  for entity in entities_involved:
592
  cardinality = cardinalities.get(entity, '1')
593
-
594
- if len(entities_involved) == 2 and entities_involved[0] == entities_involved[1]:
595
- # Relación reflexiva
596
- dot.edge(
597
- entity,
598
- rel_name,
599
- label=cardinality,
600
- color='#404040',
601
- penwidth='2',
602
- fontsize='10',
603
- fontcolor='#000000'
604
- )
605
- else:
606
- # Relación normal
607
- dot.edge(
608
- entity,
609
- rel_name,
610
- label=cardinality,
611
- color='#404040',
612
- penwidth='2',
613
- fontsize='10',
614
- fontcolor='#000000'
615
- )
616
 
617
  # Renderizar el diagrama
618
  with NamedTemporaryFile(delete=False, suffix=f'.{output_format}') as tmp:
@@ -622,4 +572,4 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
622
  except json.JSONDecodeError:
623
  return "Error: Invalid JSON format"
624
  except Exception as e:
625
- return f"Error: {str(e)}"
 
332
  {"name": "nombre_depto", "type": "regular"}
333
  ]
334
  },
 
 
 
 
 
 
 
 
 
 
 
 
335
  {
336
  "name": "PROYECTO",
337
  "type": "strong",
338
  "attributes": [
339
  {"name": "cod_proyecto", "type": "primary_key"},
340
+ {"name": "nombre_proyecto", "type": "regular"}
 
 
 
341
  ]
342
  }
343
  ],
 
349
  "cardinalities": {
350
  "EMPLEADO": "N",
351
  "DEPARTAMENTO": "1"
352
+ }
 
 
 
 
 
 
 
 
 
 
353
  },
354
  {
355
  "name": "Trabaja_en",
356
  "type": "regular",
357
+ "entities": ["EMPLEADO", "PROYECTO"],
358
  "cardinalities": {
359
+ "EMPLEADO": "M",
360
  "PROYECTO": "N"
361
  }
362
  }
 
375
  if 'entities' not in data:
376
  raise ValueError("Missing required field: entities")
377
 
378
+ # Crear grafo con configuración simple y funcional
379
  dot = graphviz.Graph(comment='ER Diagram', engine='dot')
380
+ dot.attr(rankdir='TB', bgcolor='white', pad='0.5', nodesep='1.0', ranksep='1.5')
381
+ dot.attr('node', fontname='Arial', fontsize='10')
382
+ dot.attr('edge', fontname='Arial', fontsize='9')
 
 
 
 
 
 
 
 
 
383
 
384
  entities = data.get('entities', [])
385
  relationships = data.get('relationships', [])
386
 
387
+ # Crear entidades
388
  for entity in entities:
389
  entity_name = entity.get('name')
390
  entity_type = entity.get('type', 'strong')
 
393
  continue
394
 
395
  if entity_type == 'weak':
396
+ # Entidad débil: rectángulo con doble borde
397
+ dot.node(
398
+ entity_name,
399
+ entity_name,
400
+ shape='box',
401
+ style='filled',
402
+ fillcolor='#e8e8e8',
403
+ color='#404040',
404
+ penwidth='3'
405
+ )
406
  else:
407
+ # Entidad fuerte: rectángulo simple
408
  dot.node(
409
  entity_name,
410
  entity_name,
411
  shape='box',
412
+ style='filled',
413
  fillcolor='#e8e8e8',
414
  color='#404040',
415
+ penwidth='1'
 
 
416
  )
417
 
418
  # Crear atributos para cada entidad
 
430
  # Clave primaria: elipse con texto subrayado
431
  dot.node(
432
  attr_id,
433
+ f'{attr_name}',
434
  shape='ellipse',
435
  style='filled',
436
+ fillcolor='#d8d8d8',
437
  color='#404040',
438
+ xlabel=f'PK: {attr_name}'
439
  )
440
  elif attr_type == 'partial_key':
441
+ # Clave parcial
442
  dot.node(
443
  attr_id,
444
+ attr_name,
445
  shape='ellipse',
446
  style='filled,dashed',
447
+ fillcolor='#d8d8d8',
448
+ color='#404040'
 
449
  )
450
  elif attr_type == 'multivalued':
451
+ # Atributo multivaluado: doble elipse (simulado con penwidth)
 
 
 
 
452
  dot.node(
453
  attr_id,
454
+ attr_name,
455
  shape='ellipse',
456
+ style='filled',
457
  fillcolor='#d8d8d8',
458
+ color='#404040',
459
+ penwidth='3'
460
  )
461
+ elif attr_type == 'derived':
462
+ # Atributo derivado
463
  dot.node(
464
  attr_id,
465
+ f'/{attr_name}/',
466
  shape='ellipse',
467
+ style='filled,dashed',
468
  fillcolor='#d8d8d8',
469
  color='#404040'
470
  )
 
480
  )
481
 
482
  # Conectar atributo con entidad
483
+ dot.edge(entity_name, attr_id, color='#404040')
484
 
485
  # Crear relaciones
486
  for relationship in relationships:
487
  rel_name = relationship.get('name')
488
  rel_type = relationship.get('type', 'regular')
489
+ entities_involved = relationship.get('entities', [])
490
+ cardinalities = relationship.get('cardinalities', {})
491
+ rel_attributes = relationship.get('attributes', [])
492
+
493
+ if not rel_name or len(entities_involved) < 2:
494
+ continue
495
 
496
  if rel_type == 'isa':
497
  # Relación ISA (jerarquía)
 
499
  children = relationship.get('children', [])
500
 
501
  if parent and children:
502
+ # Crear nodo ISA
 
503
  dot.node(
504
+ rel_name,
505
  'ISA',
506
  shape='triangle',
507
  style='filled',
508
+ fillcolor='#c8c8c8',
509
+ color='#404040'
 
510
  )
511
 
512
  # Conectar padre con ISA
513
+ dot.edge(parent, rel_name, color='#404040')
514
 
515
  # Conectar ISA con hijos
516
  for child in children:
517
+ dot.edge(rel_name, child, color='#404040')
518
 
519
+ elif rel_type == 'identifying':
520
+ # Relación identificadora: rombo con doble borde
521
+ dot.node(
522
+ rel_name,
523
+ rel_name,
524
+ shape='diamond',
525
+ style='filled',
526
+ fillcolor='#c8c8c8',
527
+ color='#404040',
528
+ penwidth='3'
529
+ )
530
 
531
+ # Conectar entidades
532
+ for entity in entities_involved:
533
+ cardinality = cardinalities.get(entity, '1')
534
+ dot.edge(entity, rel_name, label=cardinality, color='#404040')
535
 
536
+ else:
537
+ # Relación regular: rombo simple
538
+ dot.node(
539
+ rel_name,
540
+ rel_name,
541
+ shape='diamond',
542
+ style='filled',
543
+ fillcolor='#c8c8c8',
544
+ color='#404040'
545
+ )
 
 
 
 
 
546
 
547
+ # Crear atributos de la relación si existen
548
  for i, attr in enumerate(rel_attributes):
549
  attr_name = attr.get('name', '')
550
  attr_id = f"{rel_name}_attr_{i}"
 
562
  # Conectar entidades con la relación
563
  for entity in entities_involved:
564
  cardinality = cardinalities.get(entity, '1')
565
+ dot.edge(entity, rel_name, label=cardinality, color='#404040')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
 
567
  # Renderizar el diagrama
568
  with NamedTemporaryFile(delete=False, suffix=f'.{output_format}') as tmp:
 
572
  except json.JSONDecodeError:
573
  return "Error: Invalid JSON format"
574
  except Exception as e:
575
+ return f"Error: {str(e)}"