feat: 添加订单相关字段和自动生成规则,包括订单商品数量和支付状态;更新文档和迁移脚本
This commit is contained in:
209
script/pocketbase.ensure-order-autogen-fields.js
Normal file
209
script/pocketbase.ensure-order-autogen-fields.js
Normal file
@@ -0,0 +1,209 @@
|
||||
import { createRequire } from 'module';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import PocketBase from 'pocketbase';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
let runtimeConfig = {};
|
||||
try {
|
||||
runtimeConfig = require('../pocket-base/bai_api_pb_hooks/bai_api_shared/config/runtime.js');
|
||||
} catch (_error) {
|
||||
runtimeConfig = {};
|
||||
}
|
||||
|
||||
function readEnvFile(filePath) {
|
||||
if (!fs.existsSync(filePath)) return {};
|
||||
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
const result = {};
|
||||
|
||||
for (const rawLine of content.split(/\r?\n/)) {
|
||||
const line = rawLine.trim();
|
||||
if (!line || line.startsWith('#')) continue;
|
||||
|
||||
const index = line.indexOf('=');
|
||||
if (index === -1) continue;
|
||||
|
||||
const key = line.slice(0, index).trim();
|
||||
const value = line.slice(index + 1).trim();
|
||||
result[key] = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const backendEnv = readEnvFile(path.resolve(__dirname, '..', 'back-end', '.env'));
|
||||
const PB_URL = String(
|
||||
process.env.PB_URL
|
||||
|| backendEnv.POCKETBASE_API_URL
|
||||
|| runtimeConfig.POCKETBASE_API_URL
|
||||
|| 'http://127.0.0.1:8090'
|
||||
).replace(/\/+$/, '');
|
||||
const AUTH_TOKEN = process.env.POCKETBASE_AUTH_TOKEN || runtimeConfig.POCKETBASE_AUTH_TOKEN || '';
|
||||
|
||||
if (!AUTH_TOKEN) {
|
||||
console.error('❌ 缺少 POCKETBASE_AUTH_TOKEN,无法执行 tbl_order 自动编号迁移。');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const pb = new PocketBase(PB_URL);
|
||||
|
||||
const ORDER_ID_PATTERN = 'ORDER-[0-9]{13}-[A-Za-z0-9]{6}';
|
||||
const ORDER_NUMBER_PATTERN = '[0-9]{18}';
|
||||
|
||||
function normalizeFieldPayload(field, overrides) {
|
||||
const payload = Object.assign({}, field, overrides || {});
|
||||
|
||||
if (payload.type === 'number') {
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'onlyInt')) payload.onlyInt = !!payload.onlyInt;
|
||||
}
|
||||
|
||||
if (payload.type === 'autodate') {
|
||||
payload.onCreate = typeof payload.onCreate === 'boolean' ? payload.onCreate : true;
|
||||
payload.onUpdate = typeof payload.onUpdate === 'boolean' ? payload.onUpdate : false;
|
||||
}
|
||||
|
||||
if (payload.type === 'file') {
|
||||
payload.maxSelect = typeof payload.maxSelect === 'number' ? payload.maxSelect : 0;
|
||||
payload.maxSize = typeof payload.maxSize === 'number' ? payload.maxSize : 0;
|
||||
payload.mimeTypes = Array.isArray(payload.mimeTypes) ? payload.mimeTypes : null;
|
||||
}
|
||||
|
||||
if (payload.type === 'relation') {
|
||||
payload.maxSelect = typeof payload.maxSelect === 'number' ? payload.maxSelect : 1;
|
||||
payload.cascadeDelete = typeof payload.cascadeDelete === 'boolean' ? payload.cascadeDelete : false;
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
function buildCollectionPayload(collection, fields) {
|
||||
return {
|
||||
name: collection.name,
|
||||
type: collection.type,
|
||||
listRule: collection.listRule,
|
||||
viewRule: collection.viewRule,
|
||||
createRule: collection.createRule,
|
||||
updateRule: collection.updateRule,
|
||||
deleteRule: collection.deleteRule,
|
||||
fields,
|
||||
indexes: collection.indexes || [],
|
||||
};
|
||||
}
|
||||
|
||||
async function migrateOrderFields() {
|
||||
const collection = await pb.collections.getOne('tbl_order');
|
||||
const fields = Array.isArray(collection.fields) ? collection.fields : [];
|
||||
|
||||
const orderIdField = fields.find((field) => field && field.name === 'order_id');
|
||||
const orderNumberField = fields.find((field) => field && field.name === 'order_number');
|
||||
|
||||
if (!orderIdField || !orderNumberField) {
|
||||
throw new Error('tbl_order 缺少 order_id 或 order_number 字段');
|
||||
}
|
||||
|
||||
const orderIdReady = orderIdField.type === 'text' && String(orderIdField.autogeneratePattern || '') === ORDER_ID_PATTERN;
|
||||
const orderNumberReady = orderNumberField.type === 'text'
|
||||
&& String(orderNumberField.autogeneratePattern || '') === ORDER_NUMBER_PATTERN;
|
||||
|
||||
if (orderIdReady && orderNumberReady) {
|
||||
return {
|
||||
action: 'skipped',
|
||||
order_id: {
|
||||
type: orderIdField.type,
|
||||
autogeneratePattern: String(orderIdField.autogeneratePattern || ''),
|
||||
},
|
||||
order_number: {
|
||||
type: orderNumberField.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const nextFields = fields
|
||||
.filter((field) => field && field.name !== 'id')
|
||||
.map((field) => {
|
||||
if (field.name === 'order_id') {
|
||||
return normalizeFieldPayload(field, {
|
||||
type: 'text',
|
||||
required: true,
|
||||
autogeneratePattern: ORDER_ID_PATTERN,
|
||||
});
|
||||
}
|
||||
|
||||
if (field.name === 'order_number') {
|
||||
return normalizeFieldPayload(field, {
|
||||
type: 'text',
|
||||
required: true,
|
||||
autogeneratePattern: ORDER_NUMBER_PATTERN,
|
||||
pattern: '',
|
||||
});
|
||||
}
|
||||
|
||||
return normalizeFieldPayload(field);
|
||||
});
|
||||
|
||||
await pb.collections.update(collection.id, buildCollectionPayload(collection, nextFields));
|
||||
|
||||
return {
|
||||
action: 'updated',
|
||||
};
|
||||
}
|
||||
|
||||
async function verifyOrderFields() {
|
||||
const collection = await pb.collections.getOne('tbl_order');
|
||||
const orderIdField = (collection.fields || []).find((field) => field && field.name === 'order_id');
|
||||
const orderNumberField = (collection.fields || []).find((field) => field && field.name === 'order_number');
|
||||
|
||||
const result = {
|
||||
order_id: {
|
||||
type: orderIdField ? orderIdField.type : '',
|
||||
autogeneratePattern: String(orderIdField && orderIdField.autogeneratePattern || ''),
|
||||
ok: !!orderIdField && orderIdField.type === 'text' && String(orderIdField.autogeneratePattern || '') === ORDER_ID_PATTERN,
|
||||
},
|
||||
order_number: {
|
||||
type: orderNumberField ? orderNumberField.type : '',
|
||||
autogeneratePattern: String(orderNumberField && orderNumberField.autogeneratePattern || ''),
|
||||
ok: !!orderNumberField
|
||||
&& orderNumberField.type === 'text'
|
||||
&& String(orderNumberField.autogeneratePattern || '') === ORDER_NUMBER_PATTERN,
|
||||
},
|
||||
};
|
||||
|
||||
if (!result.order_id.ok || !result.order_number.ok) {
|
||||
throw new Error('tbl_order 自动编号规则校验失败: ' + JSON.stringify(result, null, 2));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log(`🔄 正在连接 PocketBase: ${PB_URL}`);
|
||||
pb.authStore.save(AUTH_TOKEN, null);
|
||||
console.log('✅ 已使用 POCKETBASE_AUTH_TOKEN 载入认证状态。');
|
||||
|
||||
const migrated = await migrateOrderFields();
|
||||
console.log('📝 迁移结果:');
|
||||
console.log(JSON.stringify(migrated, null, 2));
|
||||
|
||||
const verified = await verifyOrderFields();
|
||||
console.log('📝 校验结果:');
|
||||
console.log(JSON.stringify(verified, null, 2));
|
||||
|
||||
console.log('🎉 tbl_order 自动编号规则已就绪。');
|
||||
} catch (error) {
|
||||
console.error('❌ tbl_order 自动编号迁移失败:');
|
||||
console.error('status:', error && error.status);
|
||||
console.error('message:', error && error.message);
|
||||
console.error('response:', error && error.response);
|
||||
console.error('originalError:', error && error.originalError);
|
||||
console.error('stack:', error && error.stack);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user