Cảm ơn bạn đã quan tâm đến VietERP! Tài liệu này sẽ giúp bạn bắt đầu đóng góp vào dự án.
Thank you for your interest in contributing to VietERP! This guide will help you get started contributing to the project.
VietERP Platform là một dự án mã nguồn mở hướng tới cộng đồng. Chúng tôi hoan nghênh mọi đóng góp từ:
- 🐛 Báo cáo và sửa lỗi / Bug reports and fixes
- ✨ Tính năng mới / New features
- 📚 Cải tiến tài liệu / Documentation improvements
- 🔍 Kiểm thử / Testing and QA
- 🌍 Dịch và bản địa hoá / Translations
- 💬 Feedback về thiết kế / Design feedback
VietERP Platform is an open-source community-driven project. We welcome contributions of all kinds:
- Bug reports and fixes
- New features and enhancements
- Documentation improvements
- Testing and quality assurance
- Translations and localization
- Design feedback
- Node.js 18+
- npm/yarn
- PostgreSQL 16+
- Docker & Docker Compose (optional, for local database)
- Git
# 1. Fork và clone kho mã nguồn
git clone https://github.com/YOUR-USERNAME/Viet-ERP.git
cd Viet-ERP
# 2. Cài đặt dependencies
npm install --legacy-peer-deps
# 3. Sao chép file environment
cp .env.example .env.local
# 4. Khởi động PostgreSQL (Docker)
docker compose up -d postgres
# 5. Chạy migrations
npx prisma migrate deploy
# 6. Seed dữ liệu test (optional)
npx prisma db seed
# 7. Khởi động development server
npm run dev
# 8. Mở http://localhost:3000# Xem các issue cần trợ giúp
# https://github.com/lacviet-erp/Viet-ERP/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
# Nếu bạn có ý tưởng mới, hãy tạo issue trước
# Để không trùng lặp công việc# Cập nhật main
git checkout main
git pull origin main
# Tạo nhánh tính năng từ issue (vd: issue #123)
git checkout -b feature/add-customer-segments-123
# Hoặc sửa lỗi
git checkout -b fix/incorrect-tax-calculation-124
# Hoặc cải tiến tài liệu
git checkout -b docs/update-migration-guide-125Quy ước đặt tên nhánh / Branch Naming Convention:
feature/<description>-<issue-number>— Tính năng mớifix/<description>-<issue-number>— Sửa lỗidocs/<description>-<issue-number>— Tài liệurefactor/<description>-<issue-number>— Tái cấu trúctest/<description>-<issue-number>— Kiểm thửperf/<description>-<issue-number>— Hiệu suất
Tuân theo Conventional Commits format:
git commit -m "feat(crm): add customer segmentation field
- Adds 'segments' field to Customer model
- Supports JSON array of segment IDs
- Includes database migration
- Resolves #123"Format Commit Message:
<type>(<scope>): <description>
[optional body]
[optional footer: Resolves #issue-number]
Types:
feat— Tính năng mới / New featurefix— Sửa lỗi / Bug fixdocs— Tài liệu / Documentationstyle— Định dạng mã / Code stylerefactor— Tái cấu trúc / Code refactoringperf— Hiệu suất / Performance improvementtest— Kiểm thử / Testingchore— Công việc khác / Maintenanceci— CI/CD
Scopes:
hrm— Human Resource Managementcrm— Customer Relationship Managementmrp— Manufacturing Resource Planningaccounting— Accounting Moduleecommerce— E-commerce Moduleotb— OTB Moduletpm— TPM Modulepm— Project Managementcore— Core frameworkdatabase— Database schema/migrationsauth— Authenticationbranding— Branding/UI
# Chạy linter
npm run lint
# Chạy type checking
npm run typecheck
# Chạy unit tests
npm run test
# Chạy E2E tests (nếu có)
npm run test:e2e
# Kiểm thử module cụ thể
npx turbo test --filter=CRM
# Kiểm thử database migrations
npx prisma migrate status
npx prisma db pushTest Coverage Requirements:
- 80%+ code coverage for new features
- All public APIs must be tested
- E2E tests for critical user flows
Nếu thay đổi API hoặc tính năng, cập nhật:
- README.md cho repository
- docs/ folder cho detailed documentation
- Inline code comments cho complex logic
- CHANGELOG.md (sẽ được tự động tạo)
# Push nhánh
git push origin feature/add-customer-segments-123
# Tạo PR trên GitHub
# https://github.com/lacviet-erp/Viet-ERP/compare
# Hoặc sử dụng GitHub CLI
gh pr create \
--title "feat(crm): add customer segmentation" \
--body "Adds support for customer segmentation with database migration"PR Template / Mẫu Pull Request:
## 📝 Description
Brief description of changes
## 🔗 Related Issue
Resolves #issue-number
## 🧪 Testing Done
- [ ] Unit tests added/updated
- [ ] E2E tests added/updated
- [ ] Manual testing completed
## 📸 Screenshots (if UI change)
Add screenshots for frontend changes
## ✅ Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No breaking changes (or documented)
- [ ] No new warnings// ✅ DO - Use strict types, avoid any
const getCustomer = (id: string): Promise<Customer> => {
// ...
};
// ❌ DON'T - Avoid any type
const getCustomer = (id: any): Promise<any> => {
// ...
};
// ✅ DO - Export interfaces for public APIs
export interface CreateCustomerInput {
name: string;
email: string;
code: string;
}
// ✅ DO - Use Prisma types
import { Customer, Prisma } from '@prisma/client';
// ✅ DO - Prefer const over let
const customer = { name: 'ABC Inc' };
// ❌ DON'T - Reassign variables unnecessarily
let customer = { name: 'ABC Inc' };
customer = { name: 'XYZ Inc' };src/
├── components/ # React components
│ ├── CustomerForm.tsx
│ └── CustomerForm.test.tsx # Test file next to source
├── services/ # Business logic
│ ├── customerService.ts
│ └── customerService.test.ts
├── types/ # Type definitions
│ └── customer.ts
├── utils/ # Utility functions
│ ├── validation.ts
│ └── validation.test.ts
└── index.ts # Barrel export
model Customer {
id String @id @default(cuid())
/// Customer code (unique per tenant)
code String
name String
email String?
tenantId String
tenant Tenant @relation(fields: [tenantId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([code, tenantId])
@@index([tenantId, createdAt])
@@map("customers")
}Schema Best Practices:
- Add comments on important fields
- Use appropriate field types (never TEXT for codes/IDs)
- Include indexes for foreign keys and filtering
- Keep schemas aligned with business logic
// ✅ DO - Use Tailwind utilities
<div className="flex items-center justify-between gap-4 p-4 bg-white rounded-lg shadow">
<h1 className="text-xl font-semibold text-gray-900">Customers</h1>
<button className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
Add
</button>
</div>
// ✅ DO - Support dark mode
<div className="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
// ❌ DON'T - Use inline styles
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
// ❌ DON'T - Use custom CSS
<div className="custom-card">// ✅ DO - Use bilingual labels
import { labels } from '@vierp/branding';
<label>{labels.customer.name}</label>
// Renders: "Tên khách hàng / Customer Name"
// ✅ DO - Define strings in label system
// @vierp/branding/src/labels/customer.ts
export const customerLabels = {
name: 'Tên khách hàng / Customer Name',
email: 'Email / Email',
phone: 'Điện thoại / Phone Number',
};
// ❌ DON'T - Hardcode UI text
<label>Customer Name</label>
<label>Tên khách hàng</label>// Example: customerService.test.ts
import { describe, it, expect } from 'vitest';
import { createCustomer } from './customerService';
describe('CustomerService', () => {
it('should create customer with valid input', async () => {
const result = await createCustomer({
code: 'CUST001',
name: 'ABC Inc',
tenantId: 'tenant-1',
});
expect(result.id).toBeDefined();
expect(result.code).toBe('CUST001');
});
it('should reject duplicate customer code', async () => {
// Existing customer
await createCustomer({ code: 'CUST001', name: 'ABC', tenantId: 't1' });
// Should fail
expect(
createCustomer({ code: 'CUST001', name: 'XYZ', tenantId: 't1' })
).rejects.toThrow('Duplicate code');
});
});// Example: customer-flow.e2e.ts
import { test, expect } from '@playwright/test';
test.describe('Customer Management', () => {
test('should create and view customer', async ({ page }) => {
// Navigate to customer page
await page.goto('/crm/customers');
// Create new customer
await page.click('button:has-text("Add Customer")');
await page.fill('input[placeholder="Customer Code"]', 'CUST001');
await page.fill('input[placeholder="Customer Name"]', 'ABC Inc');
await page.click('button:has-text("Save")');
// Verify customer created
await expect(page.locator('text=ABC Inc')).toBeVisible();
});
});# Tạo migration
npx prisma migrate dev --name add_customer_segments
# Kiểm tra status
npx prisma migrate status
# Deploy migrations
npx prisma migrate deployXem Migration Guide cho chi tiết.
- ✅ All tests pass
- ✅ Code is linted
- ✅ Types are correct
- ✅ Documentation is updated
- ✅ No console.log in production code
- ✅ No secrets in code
- Maintainers will review within 2-5 business days
- Constructive feedback will be provided
- Author should respond to comments within reasonable time
- Once approved, maintainer will merge
- ✅ All checks pass
- ✅ At least 1 approval
- ✅ No unresolved conversations
- ✅ Branch is up to date with main
Chúng tôi vinh danh tất cả những đóng góp! Contributors sẽ được:
- Liệt kê trong CONTRIBUTORS.md
- Được ghi tên trong release notes
- Nhận badge "Contributor" trên GitHub profile
- Mời vào Discord community
- 💬 GitHub Discussions
- 🤝 Discord Community
- 📧 Email: [email protected]
- 🐦 Twitter: @VietERPDev
Dự án này tuân theo Contributor Covenant Code of Conduct.
Tóm tắt: Hãy tôn trọng nhau, không có hành vi quấy rối hoặc kỳ thị.
Q: Tôi có thể đóng góp nếu lần đầu tiên sử dụng VietERP không? A: Chắc chắn! Chúng tôi mong chờ nhất những đóng góp từ người dùng thực tế. Hãy bắt đầu với tài liệu hoặc bug reports nhỏ.
Q: Tôi cần phải xin phép trước khi bắt đầu làm việc? A: Không, nhưng nên comment trên issue để tránh trùng lặp công việc.
Q: PR của tôi bị reject. Nó có nghĩa là gì? A: Không! Đôi khi chúng tôi chỉ cần thay đổi nhỏ hoặc cần hiểu rõ hơn. Hãy thảo luận với reviewer.
Q: Làm thế nào để thêm một tính năng mới lớn? A: Hãy mở Discussion trước để đề xuất. Chúng tôi thích thảo luận ý tưởng lớn trước khi viết code.
Cảm ơn bạn đã dành thời gian để đóng góp vào VietERP Platform! 🙏
Contributions are what make VietERP better for everyone. We truly appreciate your effort!