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
|
<?php
/**
* Simplified component CSV importer — title, description, supplier, PN, price.
*
* CSV column layout (0-based, header row skipped by loader):
* 0 title Component name
* 1 description Plain-text description (stored as bithtml content body)
* 2 supplier Supplier contact title, case-insensitive (optional)
* 3 supplier_pn Supplier part number → xref #PN in xkey_ext (optional)
* 4 supplier_price Supplier price → xref #PR in xkey (optional)
*
* Supplier name is matched against liberty_content.title for content_type_guid='contact'.
* #SUP stores the contact content_id in the xref column; #PN and #PR share xorder=1
* so they are grouped with the #SUP entry as one supplier set.
*
* Existing components (matched by title) are skipped unless cleared first.
*
* @package stock
*/
use Bitweaver\Stock\StockComponent;
// Cache supplier lookups — only 4 or so suppliers in the CSV
$_stockSupplierCache = [];
function stockImportFindSupplier( string $name ): ?int {
global $gBitDb, $_stockSupplierCache;
$key = strtolower( trim( $name ) );
if( array_key_exists( $key, $_stockSupplierCache ) ) {
return $_stockSupplierCache[$key];
}
$contentId = $gBitDb->getOne(
"SELECT lc.`content_id`
FROM `".BIT_DB_PREFIX."liberty_content` lc
INNER JOIN `".BIT_DB_PREFIX."contact` c ON c.`content_id` = lc.`content_id`
WHERE UPPER( lc.`title` ) = UPPER( ? )",
[ trim( $name ) ]
);
$_stockSupplierCache[$key] = $contentId ? (int)$contentId : null;
return $_stockSupplierCache[$key];
}
function stockExpungeComponentByTitle( string $title ): bool {
global $gBitDb;
$contentId = $gBitDb->getOne(
"SELECT lc.`content_id`
FROM `".BIT_DB_PREFIX."stock_component` sc
INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON lc.`content_id` = sc.`content_id`
WHERE lc.`title` = ?",
[ $title ]
);
if( !$contentId ) {
return false;
}
// StockComponent::expunge() handles component_map + stock_component;
// LibertyContent::expunge() now handles liberty_xref + liberty_content
$component = new StockComponent( null, (int)$contentId );
$component->expunge();
return true;
}
function stockImportSimpleComponent( array $data, int $rowNum ): array {
global $gBitDb;
$result = [ 'loaded' => 0, 'skipped' => 0, 'errors' => [] ];
$title = trim( $data[0] ?? '' );
if( empty( $title ) ) {
$result['skipped']++;
$result['errors'][] = "Row $rowNum: empty title, skipped.";
return $result;
}
$exists = $gBitDb->getOne(
"SELECT lc.`content_id`
FROM `".BIT_DB_PREFIX."stock_component` sc
INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON lc.`content_id` = sc.`content_id`
WHERE lc.`title` = ?",
[ $title ]
);
if( $exists ) {
$result['skipped']++;
$result['errors'][] = "Row $rowNum: '$title' already exists, skipped.";
return $result;
}
$description = trim( $data[1] ?? '' );
$supplierName = trim( $data[2] ?? '' );
$supplierPn = trim( $data[3] ?? '' );
$supplierPrice = trim( $data[4] ?? '' );
$component = new StockComponent();
$pHash = [
'title' => $title,
'edit' => $description,
'format_guid' => 'bithtml',
];
if( !$component->store( $pHash ) ) {
$result['skipped']++;
$result['errors'][] = "Row $rowNum: failed to create component '$title'.";
return $result;
}
$contentId = $component->mContentId;
if( !empty( $supplierName ) ) {
$supplierContentId = stockImportFindSupplier( $supplierName );
if( !$supplierContentId ) {
$result['errors'][] = "Row $rowNum: '$title' — supplier '$supplierName' not found in contacts, xrefs skipped.";
} else {
$xrefId = $gBitDb->GenID( 'liberty_xref_seq' );
$gBitDb->associateInsert( BIT_DB_PREFIX.'liberty_xref', [
'xref_id' => $xrefId,
'content_id' => $contentId,
'item' => '#SUP',
'xorder' => 1,
'xref' => $supplierContentId,
'last_update_date' => $gBitDb->NOW(),
] );
if( !empty( $supplierPn ) ) {
$xrefId = $gBitDb->GenID( 'liberty_xref_seq' );
$gBitDb->associateInsert( BIT_DB_PREFIX.'liberty_xref', [
'xref_id' => $xrefId,
'content_id' => $contentId,
'item' => '#PN',
'xorder' => 1,
'xkey_ext' => substr( $supplierPn, 0, 250 ),
'last_update_date' => $gBitDb->NOW(),
] );
}
if( !empty( $supplierPrice ) ) {
$xrefId = $gBitDb->GenID( 'liberty_xref_seq' );
$gBitDb->associateInsert( BIT_DB_PREFIX.'liberty_xref', [
'xref_id' => $xrefId,
'content_id' => $contentId,
'item' => '#PR',
'xorder' => 1,
'xkey' => substr( $supplierPrice, 0, 32 ),
'last_update_date' => $gBitDb->NOW(),
] );
}
}
}
$result['loaded']++;
return $result;
}
|