#49 feat: builders de grafos de provenance (proveedores-organizaciones y territorios)
This commit is contained in:
104
src/components/provenance/provenance-graph.js
Normal file
104
src/components/provenance/provenance-graph.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Builders de grafos de provenance (específicos del dominio).
|
||||
*
|
||||
* Convierten el payload `product_provenance` del resumen de compra/pedido en
|
||||
* un grafo en capas usando el servicio genérico `services/graph/graph-layout`.
|
||||
*/
|
||||
|
||||
import { computeColumnLayout } from '@/services/graph/graph-layout'
|
||||
|
||||
const SUPPLIER_ORG_COLUMNS = { product: 0, supplier: 1, organization: 2 }
|
||||
const TERRITORY_COLUMNS = { product: 0, supplier: 1, municipality: 2, department: 3, country: 4 }
|
||||
|
||||
function makeCollector () {
|
||||
const nodes = []
|
||||
const edges = []
|
||||
const seen = new Map()
|
||||
return {
|
||||
nodes,
|
||||
edges,
|
||||
addNode (kind, entity) {
|
||||
const id = `${kind}:${entity.id}`
|
||||
if (!seen.has(id)) {
|
||||
const node = {
|
||||
id,
|
||||
kind,
|
||||
label: entity.name,
|
||||
image: entity.catalogue_images?.[0] || null,
|
||||
entity: { ...entity, kind },
|
||||
}
|
||||
seen.set(id, node)
|
||||
nodes.push(node)
|
||||
}
|
||||
return seen.get(id)
|
||||
},
|
||||
addEdge (from, to) {
|
||||
edges.push({ from, to })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function layout (collector, columns) {
|
||||
return computeColumnLayout(collector.nodes, collector.edges, {
|
||||
columnOf: node => columns[node.kind] ?? 0,
|
||||
columnWidth: 220,
|
||||
rowHeight: 72,
|
||||
padding: 24,
|
||||
})
|
||||
}
|
||||
|
||||
export function buildSupplierOrganizationGraph (provenance) {
|
||||
const g = makeCollector()
|
||||
for (const entry of provenance || []) {
|
||||
if (!entry.product) continue
|
||||
const product = g.addNode('product', entry.product)
|
||||
for (const rel of entry.suppliers || []) {
|
||||
if (!rel.supplier) continue
|
||||
const supplier = g.addNode('supplier', rel.supplier)
|
||||
g.addEdge(product.id, supplier.id)
|
||||
if (rel.organization) {
|
||||
const organization = g.addNode('organization', rel.organization)
|
||||
g.addEdge(supplier.id, organization.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return layout(g, SUPPLIER_ORG_COLUMNS)
|
||||
}
|
||||
|
||||
export function buildTerritoryGraph (provenance) {
|
||||
const g = makeCollector()
|
||||
for (const entry of provenance || []) {
|
||||
if (!entry.product) continue
|
||||
const product = g.addNode('product', entry.product)
|
||||
for (const rel of entry.suppliers || []) {
|
||||
if (!rel.supplier) continue
|
||||
const supplier = g.addNode('supplier', rel.supplier)
|
||||
g.addEdge(product.id, supplier.id)
|
||||
if (rel.municipality) {
|
||||
const municipality = g.addNode('municipality', rel.municipality)
|
||||
g.addEdge(supplier.id, municipality.id)
|
||||
if (rel.department) {
|
||||
const department = g.addNode('department', rel.department)
|
||||
g.addEdge(municipality.id, department.id)
|
||||
if (rel.country) {
|
||||
const country = g.addNode('country', rel.country)
|
||||
g.addEdge(department.id, country.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return layout(g, TERRITORY_COLUMNS)
|
||||
}
|
||||
|
||||
export function hasAnySupplier (provenance) {
|
||||
return (provenance || []).some(entry => (entry.suppliers || []).length > 0)
|
||||
}
|
||||
|
||||
export function hasAnyTerritory (provenance) {
|
||||
return (provenance || []).some(entry =>
|
||||
(entry.suppliers || []).some(rel =>
|
||||
rel.municipality || rel.department || rel.country
|
||||
)
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user