@accounter/shaam-uniform-format-generator
Version:
Fully typed application that generates, parses, and validates SHAAM uniform format tax reports (INI.TXT and BKMVDATA.TXT).
477 lines (386 loc) • 10.8 kB
Markdown
# @accounter/shaam-uniform-format-generator
A fully typed TypeScript library for generating, parsing, and validating SHAAM uniform format tax
reports (`INI.TXT` and `BKMVDATA.TXT` files).
## 🧩 Overview
This package provides a comprehensive solution for working with SHAAM (Israeli tax authority)
uniform format files. It allows you to:
1. **Generate** `INI.TXT` and `BKMVDATA.TXT` files from a high-level JSON object
2. **Parse** those files back into structured, validated JSON
3. **Validate** data against SHAAM 1.31 specifications
4. **Format** output with spec-compliant field widths, padding, and CRLF line endings
## 🚀 Features
- **Type Safety**: Full TypeScript support with strict typing
- **Validation**: Built-in Zod schemas for data validation
- **Format Compliance**: Generates files that meet SHAAM 1.31 specifications
- **Developer Experience**: Excellent autocompletion and helpful error messages
- **File System Agnostic**: Returns content in memory without writing to disk
- **Comprehensive Testing**: Full test coverage with Vitest
## 📁 Supported Record Types
### `INI.TXT`
- `A000` — Header
- `A000Sum` — Count summary records for each record type
### `BKMVDATA.TXT`
- `A100` — Business opening record
- `C100` — Document header
- `D110` — Document line
- `D120` — Payment/receipt
- `B100` — Journal entry line
- `B110` — Account
- `M100` — Inventory item
- `Z900` — Closing record
## 🛠️ Installation
```bash
npm install @accounter/shaam-uniform-format-generator
# or
yarn add @accounter/shaam-uniform-format-generator
```
## 📖 API Documentation
### Main Functions
#### `generateUniformFormatReport(input, options?)`
Generates SHAAM uniform format report files from a high-level JSON input object.
```typescript
import {
generateUniformFormatReport,
type ReportInput
} from '@accounter/shaam-uniform-format-generator'
const reportInput: ReportInput = {
business: {
businessId: '12345',
name: 'Example Business Ltd',
taxId: '123456789',
reportingPeriod: {
startDate: '2023-01-01',
endDate: '2023-12-31'
}
},
documents: [
{
id: 'INV001',
type: '320', // Invoice
date: '2023-06-15',
amount: 1000.0,
description: 'Service invoice'
}
],
journalEntries: [
{
id: 'JE001',
date: '2023-06-15',
amount: 1000.0,
accountId: '1100',
description: 'Revenue entry'
}
],
accounts: [
{
id: '1100',
name: 'Revenue Account',
type: '4', // Revenue
balance: 1000.0
}
],
inventory: [
{
id: 'ITEM001',
name: 'Service Item',
quantity: 1,
unitPrice: 1000.0
}
]
}
const result = generateUniformFormatReport(reportInput, {
validationMode: 'fail-fast', // or 'collect-all'
fileNameBase: 'my-report'
})
console.log(result.iniText) // INI.TXT content
console.log(result.dataText) // BKMVDATA.TXT content
console.log(result.summary) // Generation summary
```
#### `parseUniformFormatFiles(iniContent, dataContent)`
Parses SHAAM uniform format files back into structured JSON.
```typescript
import { parseUniformFormatFiles } from '@accounter/shaam-uniform-format-generator'
const parsedData = parseUniformFormatFiles(iniFileContent, dataFileContent)
console.log(parsedData.business) // Parsed business metadata
console.log(parsedData.documents) // Parsed documents
```
### Types and Interfaces
#### `ReportInput`
```typescript
interface ReportInput {
business: BusinessMetadata
documents: Document[]
journalEntries: JournalEntry[]
accounts: Account[]
inventory: InventoryItem[]
}
```
#### `BusinessMetadata`
```typescript
interface BusinessMetadata {
businessId: string
name: string
taxId: string
reportingPeriod: {
startDate: string // YYYY-MM-DD format
endDate: string // YYYY-MM-DD format
}
}
```
#### `Document`
```typescript
interface Document {
id: string
type: DocumentType // e.g., "320" for invoice, "330" for credit note
date: string // YYYY-MM-DD format
amount: number
description?: string
}
```
#### `JournalEntry`
```typescript
interface JournalEntry {
id: string
date: string // YYYY-MM-DD format
amount: number
accountId: string
description?: string
}
```
#### `Account`
```typescript
interface Account {
id: string
name: string
type: string // Account type code
balance: number
}
```
#### `InventoryItem`
```typescript
interface InventoryItem {
id: string
name: string
quantity: number
unitPrice: number
}
```
#### `ReportOutput`
```typescript
interface ReportOutput {
iniText: string // INI.TXT file content
dataText: string // BKMVDATA.TXT file content
iniFile: File // Virtual File object for INI.TXT
dataFile: File // Virtual File object for BKMVDATA.TXT
summary: {
totalRecords: number
perType: Record<string, number>
errors?: ValidationError[]
}
}
```
### Options
#### `GenerationOptions`
```typescript
interface GenerationOptions {
validationMode?: 'fail-fast' | 'collect-all' // Default: 'fail-fast'
fileNameBase?: string // Default: 'report'
}
```
- **`validationMode`**:
- `'fail-fast'`: Stop validation on first error and throw immediately
- `'collect-all'`: Collect all validation errors before throwing
- **`fileNameBase`**: Base name for generated files (without extension)
### Enums and Constants
The package exports comprehensive enums for SHAAM code tables:
```typescript
import {
CountryCodeEnum,
CurrencyCodeEnum,
DocumentTypeEnum,
PaymentMethodEnum
} from '@accounter/shaam-uniform-format-generator'
// Document types
const invoiceType = DocumentTypeEnum.enum['320'] // Invoice
const creditNoteType = DocumentTypeEnum.enum['330'] // Credit note
// Currency codes
const ils = CurrencyCodeEnum.enum.ILS // Israeli Shekel
const usd = CurrencyCodeEnum.enum.USD // US Dollar
// Payment methods
const cash = PaymentMethodEnum.enum['1'] // Cash
const check = PaymentMethodEnum.enum['2'] // Check
```
## 🎯 Complete Example
```typescript
import {
generateUniformFormatReport,
parseUniformFormatFiles,
type ReportInput
} from '@accounter/shaam-uniform-format-generator'
// 1. Prepare your data
const reportData: ReportInput = {
business: {
businessId: 'COMP001',
name: 'Acme Corp Ltd',
taxId: '123456789',
reportingPeriod: {
startDate: '2023-01-01',
endDate: '2023-12-31'
}
},
documents: [
{
id: 'INV-2023-001',
type: '320', // Invoice
date: '2023-03-15',
amount: 2340.0,
description: 'Consulting services'
},
{
id: 'CN-2023-001',
type: '330', // Credit note
date: '2023-04-10',
amount: -340.0,
description: 'Service adjustment'
}
],
journalEntries: [
{
id: 'JE-2023-001',
date: '2023-03-15',
amount: 2340.0,
accountId: '4000',
description: 'Consulting revenue'
},
{
id: 'JE-2023-002',
date: '2023-04-10',
amount: -340.0,
accountId: '4000',
description: 'Revenue adjustment'
}
],
accounts: [
{
id: '4000',
name: 'Consulting Revenue',
type: '4', // Revenue account
balance: 2000.0
},
{
id: '1200',
name: 'Accounts Receivable',
type: '1', // Asset account
balance: 1500.0
}
],
inventory: [
{
id: 'SERV-001',
name: 'Consulting Hour',
quantity: 20,
unitPrice: 117.0
}
]
}
// 2. Generate the files
try {
const result = generateUniformFormatReport(reportData, {
validationMode: 'fail-fast',
fileNameBase: 'quarterly-report-2023-q1'
})
// 3. Access the generated content
console.log('Generated INI.TXT:')
console.log(result.iniText)
console.log('\nGenerated BKMVDATA.TXT:')
console.log(result.dataText)
console.log('\nSummary:')
console.log(`Total records: ${result.summary.totalRecords}`)
console.log('Records per type:', result.summary.perType)
// 4. Save files (example using Node.js fs)
// import { writeFileSync } from 'fs'
// writeFileSync('report.INI.TXT', result.iniText, 'utf8')
// writeFileSync('report.BKMVDATA.TXT', result.dataText, 'utf8')
// 5. Parse files back (round-trip test)
const parsedData = parseUniformFormatFiles(result.iniText, result.dataText)
console.log('\nParsed business data:', parsedData.business)
} catch (error) {
console.error('Generation failed:', error.message)
if (error.errors) {
console.error('Validation errors:', error.errors)
}
}
```
## 🔧 Advanced Usage
### Custom Validation
```typescript
import { ReportInputSchema } from '@accounter/shaam-uniform-format-generator'
// Validate data before generation
const validationResult = ReportInputSchema.safeParse(yourData)
if (!validationResult.success) {
console.error('Validation errors:', validationResult.error.issues)
}
```
### Working with Individual Records
```typescript
import { encodeC100, parseC100, type C100Input } from '@accounter/shaam-uniform-format-generator'
// Encode a single document record
const documentRecord: C100Input = {
code: 'C100',
recordNumber: '1',
vatId: '123456789',
documentType: '320',
documentId: 'INV001',
documentIssueDate: '20230315'
// ... other fields
}
const encodedLine = encodeC100(documentRecord)
console.log(encodedLine) // Fixed-width formatted line
// Parse it back
const parsedRecord = parseC100(encodedLine)
console.log(parsedRecord) // Structured object
```
## 🏗️ Development
This project uses:
- **TypeScript** in strict mode for type safety
- **Zod** for runtime validation
- **Vitest** for testing
- **Bob the Bundler** for building
### Commands
```bash
# Development
yarn dev
# Testing
yarn test
yarn test:watch
# Building
yarn build
# Linting
yarn lint
```
## 📋 Requirements
- Node.js ^20.0.0 || >= 22
- TypeScript support
## � Error Handling
The library provides detailed error information:
```typescript
import { ShaamFormatError } from '@accounter/shaam-uniform-format-generator'
try {
const result = generateUniformFormatReport(invalidData)
} catch (error) {
if (error instanceof ShaamFormatError) {
console.error('SHAAM format error:', error.message)
console.error('Validation errors:', error.errors)
}
}
```
## �📄 License
MIT
## 🤝 Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our
repository.
## 📚 Documentation
For detailed documentation about SHAAM format specifications, see the `documentation/` folder.
## 🔗 Related
- [SHAAM Specification 1.31](documentation/) - Official specification documents
- [Israeli Tax Authority](https://www.gov.il/he/departments/taxes) - Official tax authority website