Compare commits
8 Commits
14089eb64c
...
87f6229d49
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87f6229d49 | ||
|
|
c66dc2ecf8 | ||
|
|
9ac8707921 | ||
|
|
3222e03cea | ||
|
|
4364c71bf9 | ||
|
|
752cfc28a1 | ||
|
|
82d3130188 | ||
|
|
9ef1c3baa2 |
35
.env.example
Normal file
35
.env.example
Normal file
@@ -0,0 +1,35 @@
|
||||
# ERP System Configuration
|
||||
ERP_URL=https://your-erp-system.com
|
||||
ERP_USERNAME=your_username
|
||||
ERP_PASSWORD=your_password
|
||||
|
||||
# Additional ERP Settings
|
||||
ERP_HEADLESS=true
|
||||
ERP_IGNORE_HTTPS_ERRORS=true
|
||||
ERP_AUTO_CLOSE_BROWSER=true
|
||||
|
||||
# Database Configuration - SQL Server
|
||||
SQL_SERVER_HOST=localhost
|
||||
SQL_SERVER_PORT=1433
|
||||
SQL_SERVER_DATABASE=erp_db
|
||||
SQL_SERVER_USERNAME=sa
|
||||
SQL_SERVER_PASSWORD=your_password
|
||||
|
||||
MYSQL_HOST=localhost
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_DATABASE=erp_db
|
||||
MYSQL_USERNAME=root
|
||||
MYSQL_PASSWORD=your_password
|
||||
|
||||
# Application Settings
|
||||
LOG_LEVEL=info
|
||||
DOWNLOAD_DIR=./downloads
|
||||
TEMP_DIR=./temp
|
||||
|
||||
# Legacy configurations (if needed)
|
||||
DB_SQLSERVER_DRIVER=ODBC Driver 18 for SQL Server
|
||||
DB_TRUST_SERVER_CERTIFICATE=yes
|
||||
DB_TYPE=mysql
|
||||
DB_MYSQL_HOST=192.168.31.83
|
||||
DB_MYSQL_PORT=3306
|
||||
DB_MYSQL_CHARSET=utf8mb4
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -6,4 +6,6 @@ out
|
||||
*.log*
|
||||
|
||||
#AI Agent
|
||||
.claude
|
||||
.claude
|
||||
|
||||
.env
|
||||
12338
package-lock.json
generated
Normal file
12338
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -18,20 +18,34 @@
|
||||
"build:unpack": "npm run build && electron-builder --dir",
|
||||
"build:win": "npm run build && electron-builder --win",
|
||||
"build:mac": "electron-vite build && electron-builder --mac",
|
||||
"build:linux": "electron-vite build && electron-builder --linux"
|
||||
"build:linux": "electron-vite build && electron-builder --linux",
|
||||
"test": "vitest",
|
||||
"test:run": "vitest run",
|
||||
"test:coverage": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.2",
|
||||
"@electron-toolkit/utils": "^4.0.0"
|
||||
"@electron-toolkit/utils": "^4.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"dotenv": "^17.3.1",
|
||||
"exceljs": "^4.4.0",
|
||||
"mssql": "^12.2.0",
|
||||
"mysql2": "^3.18.2",
|
||||
"playwright": "^1.58.2",
|
||||
"uuid": "^13.0.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
|
||||
"@electron-toolkit/eslint-config-ts": "^3.1.0",
|
||||
"@electron-toolkit/tsconfig": "^2.0.0",
|
||||
"@types/node": "^22.19.1",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@types/node": "^22.19.13",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"electron": "^39.2.6",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-vite": "^5.0.0",
|
||||
@@ -43,6 +57,7 @@
|
||||
"react": "^19.2.1",
|
||||
"react-dom": "^19.2.1",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^7.2.6"
|
||||
"vite": "^7.2.6",
|
||||
"vitest": "^4.0.18"
|
||||
}
|
||||
}
|
||||
|
||||
44
src/main/services/erp/locators.ts
Normal file
44
src/main/services/erp/locators.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* ERP Page Element Locators
|
||||
* Reference: playwrite/utils/ discrete_material_plan_extractor.py
|
||||
* Reference: playwrite/utils/ discrete_material_plan_cleaner.py
|
||||
*/
|
||||
|
||||
export const ERP_LOCATORS = {
|
||||
// Login Page
|
||||
login: {
|
||||
usernameInput: '#username',
|
||||
passwordInput: '#password',
|
||||
submitButton: 'button[type="submit"]',
|
||||
},
|
||||
|
||||
// Main Frame
|
||||
main: {
|
||||
mainIframe: '#mainiframe',
|
||||
loadingOverlay: '.loading-overlay',
|
||||
contentFrame: '#contentframe',
|
||||
},
|
||||
|
||||
// Extractor (Data Export) Page
|
||||
extractor: {
|
||||
orderNumberInput: 'input[name="orderNumber"]',
|
||||
queryButton: 'button:has-text("查询")',
|
||||
exportButton: 'button:has-text("导出")',
|
||||
},
|
||||
|
||||
// Cleaner (Material Delete) Page
|
||||
cleaner: {
|
||||
orderNumberInput: 'input[name="orderNumber"]',
|
||||
materialGrid: 'table.material-grid tbody tr',
|
||||
saveButton: 'button:has-text("保存")',
|
||||
},
|
||||
|
||||
// Common Elements
|
||||
common: {
|
||||
successMessage: '.message.success',
|
||||
errorMessage: '.message.error',
|
||||
confirmDialog: '.confirm-dialog',
|
||||
confirmButton: 'button:has-text("确定")',
|
||||
cancelButton: 'button:has-text("取消")',
|
||||
},
|
||||
};
|
||||
21
src/main/types/cleaner.types.ts
Normal file
21
src/main/types/cleaner.types.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export interface CleanerInput {
|
||||
orderNumbers: string[];
|
||||
materialCodes: string[];
|
||||
dryRun: boolean;
|
||||
onProgress?: (message: string, progress: number) => void;
|
||||
}
|
||||
|
||||
export interface CleanerResult {
|
||||
ordersProcessed: number;
|
||||
materialsDeleted: number;
|
||||
materialsSkipped: number;
|
||||
errors: string[];
|
||||
details: OrderCleanDetail[];
|
||||
}
|
||||
|
||||
export interface OrderCleanDetail {
|
||||
orderNumber: string;
|
||||
materialsDeleted: number;
|
||||
materialsSkipped: number;
|
||||
errors: string[];
|
||||
}
|
||||
16
src/main/types/erp.types.ts
Normal file
16
src/main/types/erp.types.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export interface ErpConfig {
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface ErpSession {
|
||||
browser: import('playwright').Browser;
|
||||
context: import('playwright').BrowserContext;
|
||||
page: import('playwright').Page;
|
||||
isLoggedIn: boolean;
|
||||
}
|
||||
|
||||
export interface ProgressCallback {
|
||||
(message: string, progress?: number): void;
|
||||
}
|
||||
17
src/main/types/extractor.types.ts
Normal file
17
src/main/types/extractor.types.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface ExtractorInput {
|
||||
orderNumbers: string[];
|
||||
batchSize?: number;
|
||||
onProgress?: (message: string, progress: number) => void;
|
||||
}
|
||||
|
||||
export interface ExtractorResult {
|
||||
downloadedFiles: string[];
|
||||
mergedFile: string | null;
|
||||
recordCount: number;
|
||||
errors: string[];
|
||||
}
|
||||
|
||||
export interface OrderInfo {
|
||||
orderNumber: string;
|
||||
productionId: string;
|
||||
}
|
||||
15
tests/setup.ts
Normal file
15
tests/setup.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { beforeAll, afterAll } from 'vitest';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config({ path: '.env' });
|
||||
|
||||
beforeAll(async () => {
|
||||
// Global test setup
|
||||
console.log('Test suite starting...');
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
// Global test teardown
|
||||
console.log('Test suite completed.');
|
||||
});
|
||||
26
tests/unit/locators.test.ts
Normal file
26
tests/unit/locators.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { ERP_LOCATORS } from '../../src/main/services/erp/locators';
|
||||
|
||||
describe('ERP Locators', () => {
|
||||
it('should have login page locators defined', () => {
|
||||
expect(ERP_LOCATORS.login.usernameInput).toBeDefined();
|
||||
expect(ERP_LOCATORS.login.passwordInput).toBeDefined();
|
||||
expect(ERP_LOCATORS.login.submitButton).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have main frame locator', () => {
|
||||
expect(ERP_LOCATORS.main.mainIframe).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have extractor page locators', () => {
|
||||
expect(ERP_LOCATORS.extractor.orderNumberInput).toBeDefined();
|
||||
expect(ERP_LOCATORS.extractor.queryButton).toBeDefined();
|
||||
expect(ERP_LOCATORS.extractor.exportButton).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have cleaner page locators', () => {
|
||||
expect(ERP_LOCATORS.cleaner.orderNumberInput).toBeDefined();
|
||||
expect(ERP_LOCATORS.cleaner.materialGrid).toBeDefined();
|
||||
expect(ERP_LOCATORS.cleaner.saveButton).toBeDefined();
|
||||
});
|
||||
});
|
||||
14
vitest.config.ts
Normal file
14
vitest.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
include: ['tests/**/*.{test,spec}.{ts,tsx}'],
|
||||
exclude: ['node_modules', 'dist', 'out'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['text', 'json', 'html'],
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user