Task 549: .PIE File Format
Task 549: .PIE File Format
File Format Specifications for the .PIE File Format
The .PIE file format refers to the Portfolio Investment Entity (PIE) returns file used for tax reporting to New Zealand's Inland Revenue (IRD). It is an ASCII comma-delimited CSV format (typically with .csv or .txt extension, but referred to as PIE returns file in documentation; I will treat it as .PIE for this task). The file can contain multiple records of the same type, with each record on a single line ending with CR or LF. There are three record types: PIE Periodic Return (IR852), Annual Reconciliation Return (IR853), and Investor Certificates (IR854). Files can be zipped for grouped submission. Validation includes data types, lengths, mandatory fields, and specific rules (e.g., IRD number check-digit). The format has versions (e.g., 0003, 0004 for IR852/IR853; 0005 for IR854).
- List of all the properties of this file format intrinsic to its file system:
The properties (fields) are specific to each record type and version. All fields are comma-separated, with no embedded commas in strings. Decimal fields are in format NNNNN.NN (no currency symbols, commas, or signs for positive; negative have leading -). Dates are CCYYMMDD. Strings have restricted characters (A-Z, a-z, 0-9, !`#%@$&^*()_+-{=|};: '"<>?. /). The list below includes field name, type, size/length, required status, and possible values/rules for each record type.
General Properties (Intrinsic to the Format):
- File Encoding: ASCII
- Delimiter: Comma (,)
- Line Terminator: CR or LF
- File Extension: .csv or .txt (referred to as .PIE in context)
- Compression: Optional (ZIP, TAR, GZIP for grouped files, no nesting)
- File Name Convention: e.g., PIEReturns-CCYYMMDD-NNN.csv (unique, period-based)
- Invalid Characters in Names: No [, ], , ~ or embedded commas
- Validation Rules: Mandatory fields, data types, lengths, IRD modulus 11 check, PIR values, date formats
IR852 (PIE Periodic Return) Properties (Fields) - Version 0003 (37 fields):
- PIE Return type: String (5), required, "IR852"
- Version Number: String (4), required, "0003"
- PIE Name: String (74), required
- IR Number: Integer (8-9), required
- Period End Date: Date (8), required
- Total investment asset value: Decimal (14/2), required
- Gross Income: Decimal (15/2), required
- Deductible Expenses: Decimal (15/2), required
- Net Income/Loss: Decimal (15/2), required
- Net Land Class Income/Loss: Decimal (15/2), required
- Combined Income/Loss: Decimal (15/2), required
- Formation Loss Used: Decimal (14/2), required
- Land Class Loss Brought Forward: Decimal (14/2), required
- Land Class Loss amount to Carry Forward: Decimal (14/2), required
- Land Class Loss claimed: Decimal (14/2), required
- Taxable Income: Decimal (14/2), required
- Taxable Loss: Decimal (14/2), required
- Income/Loss not attributed Taxed @ Top PIR: Decimal (15/2), required
- Income/Loss of Exited Zero-rate Investors: Decimal (15/2), required
- Investor expenses less credits for fees: Decimal (15/2), required
- Total Income To Attribute: Decimal (14/2), required
- Total Loss To Attribute: Decimal (14/2), required
- Income Attributed to 0% PIR: Decimal (14/2), required
- Loss Attributed to 0% PIR: Decimal (14/2), required
- Income Attributed to Low PIR: Decimal (14/2), required
- Loss Attributed to Low PIR: Decimal (14/2), required
- Income Attributed to Mid PIR: Decimal (14/2), required
- Loss Attributed to Mid PIR: Decimal (14/2), required
- Income Attributed to Top PIR: Decimal (14/2), required
- Loss Attributed to Top PIR: Decimal (14/2), required
- Tax Liability/Credit: Decimal (15/2), required
- Zero-rated Exited Investor’s Tax payment for Exit Period: Decimal (14/2), required
- Net Tax Liability/Credit: Decimal (15/2), required
- Foreign Tax Credit: Decimal (15/2), required
- Other Tax Credits: Decimal (15/2), required
- Imputation Credit: Decimal (15/2), required
- Resident Withholding Tax: Decimal (15/2), required
IR852 (PIE Periodic Return) Properties (Fields) - Version 0004 (39 fields):
- Same as Version 0003 for fields 1-37, with Version Number "0004"
- Income Attributed to NFI: Decimal (15/2), required
- Tax paid on NFI Income: Decimal (15/2), required
IR853 (Annual Reconciliation Return) Properties (Fields) - Version 0003 (18 fields):
- PIE Return type: String (5), required, "IR853"
- Version Number: String (4), required, "0003"
- PIE Name: String (74), required
- IR Number: Integer (8-9), required
- Period End Date: Date (8), required
- Total Number of Certificates: Integer (8), required
- Taxable Income/Loss: Decimal (15/2), required
- Total Tax Credits used for low, mid and top PIR Investors: Decimal (15/2), required
- PIE Tax Paid / Credited on Investor’s Income for low, mid and top PIR: Decimal (15/2), required
- Taxable Income/Loss Taxed at low and/or mid rate(s): Decimal (15/2), required
- PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s): Decimal (15/2), required
- Total Tax Credits on Investor’s income low and/or mid rate(s): Decimal (15/2), required
- Zero-rated Exited Investor Taxable Income / Loss: Decimal (15/2), required
- Total Zero-rated Attributed Foreign Tax Credits: Decimal (15/2), required
- Total Zero-rated Attributed Other /MAC Tax Credits: Decimal (15/2), required
- Total Zero-rated Attributed IC Tax Credits: Decimal (15/2), required
- Total Zero-rated Attributed RWT Tax Credits: Decimal (15/2), required
- Zero-rated Exited Investor’s Tax payment for Exit Period: Decimal (14/2), required
IR853 (Annual Reconciliation Return) Properties (Fields) - Version 0004 (18 fields):
- Same as Version 0003, with Version Number "0004" and slight field name variations for clarity (e.g., "Total Income/Loss" for field 7)
IR854 (Investor Certificates) Properties (Fields) - Parent Record (PIEC, 30 fields, Version 0005):
- Detail record indicator Parent: String (4), required, "PIEC"
- PIE Return Type: String (6), required, "IR854"
- Version Number: String (4), required, "0005"
- PIE Name: String (74), required
- PIE IR Number: Integer (9), required
- Period End Date: Date (8), required
- Investor’s Name: String (74), required
- Investor’s IR Number: Integer (9), optional
- Investor Certificate Identifier: String (20), required
- Prescribed Investor Rate (PIR) as at Year-end: Decimal (11/2), required
- Was PIR changed during the year?: String (1), required
- Total Income/Loss: Decimal (15/2), required
- Taxable Income/Loss: Decimal (15/2), required
- PIE Tax Paid / Credited: Decimal (15/2), required
- Foreign Tax Credits: Decimal (15/2), required
- Other Tax Credits: Decimal (15/2), required
- Imputation Credits: Decimal (15/2), required
- Resident Withholding Tax: Decimal (15/2), required
- Units Held at Year-end: Decimal (18/5), required
- Country Code: String (2), required
- Address Line 1: String (74), optional
- Address Line 2: String (74), optional
- Address Line 3: String (74), optional
- Post Code: String (10), optional
- Country: String (50), optional
- Email Address: String (100), optional
- Phone Number: String (20), optional
- Number of Joint Holders: Integer (1), required
- Joint Holder 1 Name: String (74), optional
- Joint Holder 1 IR Number: Integer (9), optional
IR854 (Investor Certificates) Properties (Fields) - Child Record (PIEJ, 3 fields, Version 0005):
- Detail record indicator Joint: String (4), required, "PIEJ"
- Joint Holder Name: String (74), required
- Joint Holder IR Number: Integer (9), optional
- Two direct download links for files of format .PIE:
No direct download links for sample .PIE files were found in public sources. The specification PDF contains example record lines, but no downloadable files. You can generate samples based on the spec for testing.
- Ghost blog embedded HTML JavaScript for drag and drop .PIE file to dump properties:
- Python class for opening, decoding, reading, writing, and printing .PIE properties:
import csv
import io
class PieFileHandler:
def __init__(self, filepath):
self.filepath = filepath
self.records = []
self.field_names = {
'IR852_0003': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total investment asset value', 'Gross Income', 'Deductible Expenses', 'Net Income/Loss', 'Net Land Class Income/Loss', 'Combined Income/Loss', 'Formation Loss Used', 'Land Class Loss Brought Forward', 'Land Class Loss amount to Carry Forward', 'Land Class Loss claimed', 'Taxable Income', 'Taxable Loss', 'Income/Loss not attributed Taxed @ Top PIR', 'Income/Loss of Exited Zero-rate Investors', 'Investor expenses less credits for fees', 'Total Income To Attribute', 'Total Loss To Attribute', 'Income Attributed to 0% PIR', 'Loss Attributed to 0% PIR', 'Income Attributed to Low PIR', 'Loss Attributed to Low PIR', 'Income Attributed to Mid PIR', 'Loss Attributed to Mid PIR', 'Income Attributed to Top PIR', 'Loss Attributed to Top PIR', 'Tax Liability/Credit', 'Zero-rated Exited Investor’s Tax payment for Exit Period', 'Net Tax Liability/Credit', 'Foreign Tax Credit', 'Other Tax Credits', 'Imputation Credit', 'Resident Withholding Tax'],
'IR852_0004': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total investment asset value', 'Gross Income', 'Deductible Expenses', 'Net Income/Loss', 'Net Land Class Income/Loss', 'Combined Income/Loss', 'Formation Loss Used', 'Land Class Loss Brought Forward', 'Land Class Loss amount to Carry Forward', 'Land Class Loss claimed', 'Taxable Income', 'Taxable Loss', 'Income/Loss not attributed Taxed @ Top PIR', 'Income/Loss of Exited Zero-rate Investors', 'Investor expenses less credits for fees', 'Total Income To Attribute', 'Total Loss To Attribute', 'Income Attributed to 0% PIR', 'Loss Attributed to 0% PIR', 'Income Attributed to Low PIR', 'Loss Attributed to Low PIR', 'Income Attributed to Mid PIR', 'Loss Attributed to Mid PIR', 'Income Attributed to Top PIR', 'Loss Attributed to Top PIR', 'Tax Liability/Credit', 'Zero-rated Exited Investor’s Tax payment for Exit Period', 'Net Tax Liability/Credit', 'Foreign Tax Credit', 'Other Tax Credits', 'Imputation Credit', 'Resident Withholding Tax', 'Income Attributed to NFI', 'Tax paid on NFI Income'],
'IR853_0003': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total Number of Certificates', 'Taxable Income/Loss', 'Total Tax Credits used for low, mid and top PIR Investors', 'PIE Tax Paid / Credited on Investor’s Income for low, mid and top PIR', 'Taxable Income/Loss Taxed at low and/or mid rate(s)', 'PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)', 'Total Tax Credits on Investor’s income low and/or mid rate(s)', 'Zero-rated Exited Investor Taxable Income / Loss', 'Total Zero-rated Attributed Foreign Tax Credits', 'Total Zero-rated Attributed Other /MAC Tax Credits', 'Total Zero-rated Attributed IC Tax Credits', 'Total Zero-rated Attributed RWT Tax Credits', 'Zero-rated Exited Investor’s Tax payment for Exit Period'],
'IR853_0004': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total Number of Certificates', 'Total Income/Loss', 'Total Tax Credits used', 'PIE Tax Paid / Credited', 'Taxable Income/Loss Taxed at low and/or mid rate(s)', 'PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)', 'Total Tax Credits on Investor’s income low and/or mid rate(s)', 'Zero-rated Exited Investor Taxable Income / Loss', 'Total Zero-rated Attributed Foreign Tax Credits', 'Total Zero-rated Attributed Other /MAC Tax Credits', 'Total Zero-rated Attributed IC Tax Credits', 'Total Zero-rated Attributed RWT Tax Credits', 'Zero-rated Exited Investor’s Tax payment for Exit Period'],
'PIEC': ['Detail record indicator Parent', 'PIE Return Type', 'Version Number', 'PIE Name', 'PIE IR Number', 'Period End Date', 'Investor’s Name', 'Investor’s IR Number', 'Investor Certificate Identifier', 'Prescribed Investor Rate (PIR) as at Year-end', 'Was PIR changed during the year?', 'Total Income/Loss', 'Taxable Income/Loss', 'PIE Tax Paid / Credited', 'Foreign Tax Credits', 'Other Tax Credits', 'Imputation Credits', 'Resident Withholding Tax', 'Units Held at Year-end', 'Country Code', 'Address Line 1', 'Address Line 2', 'Address Line 3', 'Post Code', 'Country', 'Email Address', 'Phone Number', 'Number of Joint Holders', 'Joint Holder 1 Name', 'Joint Holder 1 IR Number'],
'PIEJ': ['Detail record indicator Joint', 'Joint Holder Name', 'Joint Holder IR Number']
}
def read(self):
with open(self.filepath, 'r', encoding='ascii') as f:
reader = csv.reader(f)
for row in reader:
if row:
type_key = row[0]
version = row[1] if len(row) > 1 else ''
key = type_key if type_key in ['PIEC', 'PIEJ'] else f'{type_key}_{version}'
if key in self.field_names and len(row) == len(self.field_names[key]):
self.records.append(dict(zip(self.field_names[key], row)))
return self.records
def print_properties(self):
records = self.read()
for idx, record in enumerate(records, 1):
print(f"Record {idx}:")
for key, value in record.items():
print(f" {key}: {value}")
def write(self, new_records):
with open(self.filepath, 'w', encoding='ascii') as f:
for record in new_records:
type_key = record.get('PIE Return type') or record.get('Detail record indicator Parent') or record.get('Detail record indicator Joint')
version = record.get('Version Number', '')
key = type_key if type_key in ['PIEC', 'PIEJ'] else f'{type_key}_{version}'
if key in self.field_names:
writer = csv.writer(f)
writer.writerow([record.get(name, '') for name in self.field_names[key]])
# Example usage:
# handler = PieFileHandler('example.pie')
# handler.print_properties()
# handler.write([{'PIE Return type': 'IR852', 'Version Number': '0003', ...}])
- Java class for opening, decoding, reading, writing, and printing .PIE properties:
import java.io.*;
import java.util.*;
public class PieFileHandler {
private String filepath;
private List<Map<String, String>> records = new ArrayList<>();
private Map<String, List<String>> fieldNames = new HashMap<>();
public PieFileHandler(String filepath) {
this.filepath = filepath;
fieldNames.put("IR852_0003", Arrays.asList("PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total investment asset value", "Gross Income", "Deductible Expenses", "Net Income/Loss", "Net Land Class Income/Loss", "Combined Income/Loss", "Formation Loss Used", "Land Class Loss Brought Forward", "Land Class Loss amount to Carry Forward", "Land Class Loss claimed", "Taxable Income", "Taxable Loss", "Income/Loss not attributed Taxed @ Top PIR", "Income/Loss of Exited Zero-rate Investors", "Investor expenses less credits for fees", "Total Income To Attribute", "Total Loss To Attribute", "Income Attributed to 0% PIR", "Loss Attributed to 0% PIR", "Income Attributed to Low PIR", "Loss Attributed to Low PIR", "Income Attributed to Mid PIR", "Loss Attributed to Mid PIR", "Income Attributed to Top PIR", "Loss Attributed to Top PIR", "Tax Liability/Credit", "Zero-rated Exited Investor’s Tax payment for Exit Period", "Net Tax Liability/Credit", "Foreign Tax Credit", "Other Tax Credits", "Imputation Credit", "Resident Withholding Tax"));
fieldNames.put("IR852_0004", Arrays.asList("PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total investment asset value", "Gross Income", "Deductible Expenses", "Net Income/Loss", "Net Land Class Income/Loss", "Combined Income/Loss", "Formation Loss Used", "Land Class Loss Brought Forward", "Land Class Loss amount to Carry Forward", "Land Class Loss claimed", "Taxable Income", "Taxable Loss", "Income/Loss not attributed Taxed @ Top PIR", "Income/Loss of Exited Zero-rate Investors", "Investor expenses less credits for fees", "Total Income To Attribute", "Total Loss To Attribute", "Income Attributed to 0% PIR", "Loss Attributed to 0% PIR", "Income Attributed to Low PIR", "Loss Attributed to Low PIR", "Income Attributed to Mid PIR", "Loss Attributed to Mid PIR", "Income Attributed to Top PIR", "Loss Attributed to Top PIR", "Tax Liability/Credit", "Zero-rated Exited Investor’s Tax payment for Exit Period", "Net Tax Liability/Credit", "Foreign Tax Credit", "Other Tax Credits", "Imputation Credit", "Resident Withholding Tax", "Income Attributed to NFI", "Tax paid on NFI Income"));
fieldNames.put("IR853_0003", Arrays.asList("PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total Number of Certificates", "Taxable Income/Loss", "Total Tax Credits used for low, mid and top PIR Investors", "PIE Tax Paid / Credited on Investor’s Income for low, mid and top PIR", "Taxable Income/Loss Taxed at low and/or mid rate(s)", "PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)", "Total Tax Credits on Investor’s income low and/or mid rate(s)", "Zero-rated Exited Investor Taxable Income / Loss", "Total Zero-rated Attributed Foreign Tax Credits", "Total Zero-rated Attributed Other /MAC Tax Credits", "Total Zero-rated Attributed IC Tax Credits", "Total Zero-rated Attributed RWT Tax Credits", "Zero-rated Exited Investor’s Tax payment for Exit Period"));
fieldNames.put("IR853_0004", Arrays.asList("PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total Number of Certificates", "Total Income/Loss", "Total Tax Credits used", "PIE Tax Paid / Credited", "Taxable Income/Loss Taxed at low and/or mid rate(s)", "PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)", "Total Tax Credits on Investor’s income low and/or mid rate(s)", "Zero-rated Exited Investor Taxable Income / Loss", "Total Zero-rated Attributed Foreign Tax Credits", "Total Zero-rated Attributed Other /MAC Tax Credits", "Total Zero-rated Attributed IC Tax Credits", "Total Zero-rated Attributed RWT Tax Credits", "Zero-rated Exited Investor’s Tax payment for Exit Period"));
fieldNames.put("PIEC", Arrays.asList("Detail record indicator Parent", "PIE Return Type", "Version Number", "PIE Name", "PIE IR Number", "Period End Date", "Investor’s Name", "Investor’s IR Number", "Investor Certificate Identifier", "Prescribed Investor Rate (PIR) as at Year-end", "Was PIR changed during the year?", "Total Income/Loss", "Taxable Income/Loss", "PIE Tax Paid / Credited", "Foreign Tax Credits", "Other Tax Credits", "Imputation Credits", "Resident Withholding Tax", "Units Held at Year-end", "Country Code", "Address Line 1", "Address Line 2", "Address Line 3", "Post Code", "Country", "Email Address", "Phone Number", "Number of Joint Holders", "Joint Holder 1 Name", "Joint Holder 1 IR Number"));
fieldNames.put("PIEJ", Arrays.asList("Detail record indicator Joint", "Joint Holder Name", "Joint Holder IR Number"));
}
public void read() throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filepath))) {
String line;
while (line = br.readLine() != null) {
if (line.trim().isEmpty()) continue;
String[] fields = line.split(",", -1);
String type = fields[0];
String version = fields.length > 1 ? fields[1] : "";
String key = type.equals("PIEC") || type.equals("PIEJ") ? type : type + "_" + version;
if (fieldNames.containsKey(key) && fields.length == fieldNames.get(key).size()) {
Map<String, String> record = new LinkedHashMap<>();
List<String> names = fieldNames.get(key);
for (int i = 0; i < names.size(); i++) {
record.put(names.get(i), fields[i].trim());
}
records.add(record);
}
}
}
}
public void printProperties() throws IOException {
read();
for (int i = 0; i < records.size(); i++) {
System.out.println("Record " + (i + 1) + ":");
for (Map.Entry<String, String> entry : records.get(i).entrySet()) {
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
}
}
}
public void write(List<Map<String, String>> newRecords) throws IOException {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filepath))) {
for (Map<String, String> record : newRecords) {
String type = record.get("PIE Return type") != null ? record.get("PIE Return type") : record.get("Detail record indicator Parent") != null ? "PIEC" : "PIEJ";
String version = record.get("Version Number");
String key = type.equals("PIEC") || type.equals("PIEJ") ? type : type + "_" + version;
if (fieldNames.containsKey(key)) {
List<String> names = fieldNames.get(key);
StringBuilder line = new StringBuilder();
for (String name : names) {
line.append(record.getOrDefault(name, "")).append(",");
}
bw.write(line.substring(0, line.length() - 1));
bw.newLine();
}
}
}
}
public static void main(String[] args) throws IOException {
PieFileHandler handler = new PieFileHandler("example.pie");
handler.printProperties();
// handler.write(new ArrayList<>());
}
}
- JavaScript class for opening, decoding, reading, writing, and printing .PIE properties:
class PieFileHandler {
constructor(filepath) {
this.filepath = filepath;
this.records = [];
this.fieldNames = {
'IR852_0003': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total investment asset value', 'Gross Income', 'Deductible Expenses', 'Net Income/Loss', 'Net Land Class Income/Loss', 'Combined Income/Loss', 'Formation Loss Used', 'Land Class Loss Brought Forward', 'Land Class Loss amount to Carry Forward', 'Land Class Loss claimed', 'Taxable Income', 'Taxable Loss', 'Income/Loss not attributed Taxed @ Top PIR', 'Income/Loss of Exited Zero-rate Investors', 'Investor expenses less credits for fees', 'Total Income To Attribute', 'Total Loss To Attribute', 'Income Attributed to 0% PIR', 'Loss Attributed to 0% PIR', 'Income Attributed to Low PIR', 'Loss Attributed to Low PIR', 'Income Attributed to Mid PIR', 'Loss Attributed to Mid PIR', 'Income Attributed to Top PIR', 'Loss Attributed to Top PIR', 'Tax Liability/Credit', 'Zero-rated Exited Investor’s Tax payment for Exit Period', 'Net Tax Liability/Credit', 'Foreign Tax Credit', 'Other Tax Credits', 'Imputation Credit', 'Resident Withholding Tax'],
'IR852_0004': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total investment asset value', 'Gross Income', 'Deductible Expenses', 'Net Income/Loss', 'Net Land Class Income/Loss', 'Combined Income/Loss', 'Formation Loss Used', 'Land Class Loss Brought Forward', 'Land Class Loss amount to Carry Forward', 'Land Class Loss claimed', 'Taxable Income', 'Taxable Loss', 'Income/Loss not attributed Taxed @ Top PIR', 'Income/Loss of Exited Zero-rate Investors', 'Investor expenses less credits for fees', 'Total Income To Attribute', 'Total Loss To Attribute', 'Income Attributed to 0% PIR', 'Loss Attributed to 0% PIR', 'Income Attributed to Low PIR', 'Loss Attributed to Low PIR', 'Income Attributed to Mid PIR', 'Loss Attributed to Mid PIR', 'Income Attributed to Top PIR', 'Loss Attributed to Top PIR', 'Tax Liability/Credit', 'Zero-rated Exited Investor’s Tax payment for Exit Period', 'Net Tax Liability/Credit', 'Foreign Tax Credit', 'Other Tax Credits', 'Imputation Credit', 'Resident Withholding Tax', 'Income Attributed to NFI', 'Tax paid on NFI Income'],
'IR853_0003': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total Number of Certificates', 'Taxable Income/Loss', 'Total Tax Credits used for low, mid and top PIR Investors', 'PIE Tax Paid / Credited on Investor’s Income for low, mid and top PIR', 'Taxable Income/Loss Taxed at low and/or mid rate(s)', 'PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)', 'Total Tax Credits on Investor’s income low and/or mid rate(s)', 'Zero-rated Exited Investor Taxable Income / Loss', 'Total Zero-rated Attributed Foreign Tax Credits', 'Total Zero-rated Attributed Other /MAC Tax Credits', 'Total Zero-rated Attributed IC Tax Credits', 'Total Zero-rated Attributed RWT Tax Credits', 'Zero-rated Exited Investor’s Tax payment for Exit Period'],
'IR853_0004': ['PIE Return type', 'Version Number', 'PIE Name', 'IR Number', 'Period End Date', 'Total Number of Certificates', 'Total Income/Loss', 'Total Tax Credits used', 'PIE Tax Paid / Credited', 'Taxable Income/Loss Taxed at low and/or mid rate(s)', 'PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)', 'Total Tax Credits on Investor’s income low and/or mid rate(s)', 'Zero-rated Exited Investor Taxable Income / Loss', 'Total Zero-rated Attributed Foreign Tax Credits', 'Total Zero-rated Attributed Other /MAC Tax Tax Credits', 'Total Zero-rated Attributed IC Tax Credits', 'Total Zero-rated Attributed RWT Tax Credits', 'Zero-rated Exited Investor’s Tax payment for Exit Period'],
'PIEC': ['Detail record indicator Parent', 'PIE Return Type', 'Version Number', 'PIE Name', 'PIE IR Number', 'Period End Date', 'Investor’s Name', 'Investor’s IR Number', 'Investor Certificate Identifier', 'Prescribed Investor Rate (PIR) as at Year-end', 'Was PIR changed during the year?', 'Total Income/Loss', 'Taxable Income/Loss', 'PIE Tax Paid / Credited', 'Foreign Tax Credits', 'Other Tax Credits', 'Imputation Credits', 'Resident Withholding Tax', 'Units Held at Year-end', 'Country Code', 'Address Line 1', 'Address Line 2', 'Address Line 3', 'Post Code', 'Country', 'Email Address', 'Phone Number', 'Number of Joint Holders', 'Joint Holder 1 Name', 'Joint Holder 1 IR Number'],
'PIEJ': ['Detail record indicator Joint', 'Joint Holder Name', 'Joint Holder IR Number']
};
}
async read() {
// For node.js, use fs
const fs = require('fs');
const text = fs.readFileSync(this.filepath, 'ascii');
const lines = text.split(/\r?\n/);
lines.forEach(line => {
if (line.trim() === '') return;
const fields = line.split(',');
const type = fields[0];
const version = fields[1] || '';
const key = (type === 'PIEC' || type === 'PIEJ') ? type : `${type}_${version}`;
if (this.fieldNames[key] && fields.length === this.fieldNames[key].length) {
const record = {};
this.fieldNames[key].forEach((name, i) => {
record[name] = fields[i].trim();
});
this.records.push(record);
}
});
return this.records;
}
async printProperties() {
await this.read();
this.records.forEach((record, idx) => {
console.log(`Record ${idx + 1}:`);
for (const [key, value] in Object.entries(record)) {
console.log(` ${key}: ${value}`);
}
});
}
async write(newRecords) {
const fs = require('fs');
let content = '';
newRecords.forEach(record => {
const type = record['PIE Return type'] || (record['Detail record indicator Parent'] ? 'PIEC' : 'PIEJ');
const version = record['Version Number'] || '';
const key = (type === 'PIEC' || type === 'PIEJ') ? type : `${type}_${version}`;
if (this.fieldNames[key]) {
content += this.fieldNames[key].map(name => record[name] || '').join(',') + '\n';
}
});
fs.writeFileSync(this.filepath, content, 'ascii');
}
}
// Example usage:
// const handler = new PieFileHandler('example.pie');
// handler.printProperties();
- C class for opening, decoding, read, write, and print to console all the properties from the above list:
Since C does not have built-in classes like C++, I'll use C++ for the "c class" as it's common for such tasks.
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <string>
class PieFileHandler {
private:
std::string filepath;
std::vector<std::map<std::string, std::string>> records;
std::map<std::string, std::vector<std::string>> fieldNames;
public:
PieFileHandler(std::string filepath) : filepath(filepath) {
fieldNames["IR852_0003"] = {"PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total investment asset value", "Gross Income", "Deductible Expenses", "Net Income/Loss", "Net Land Class Income/Loss", "Combined Income/Loss", "Formation Loss Used", "Land Class Loss Brought Forward", "Land Class Loss amount to Carry Forward", "Land Class Loss claimed", "Taxable Income", "Taxable Loss", "Income/Loss not attributed Taxed @ Top PIR", "Income/Loss of Exited Zero-rate Investors", "Investor expenses less credits for fees", "Total Income To Attribute", "Total Loss To Attribute", "Income Attributed to 0% PIR", "Loss Attributed to 0% PIR", "Income Attributed to Low PIR", "Loss Attributed to Low PIR", "Income Attributed to Mid PIR", "Loss Attributed to Mid PIR", "Income Attributed to Top PIR", "Loss Attributed to Top PIR", "Tax Liability/Credit", "Zero-rated Exited Investor’s Tax payment for Exit Period", "Net Tax Liability/Credit", "Foreign Tax Credit", "Other Tax Credits", "Imputation Credit", "Resident Withholding Tax"};
fieldNames["IR852_0004"] = {"PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total investment asset value", "Gross Income", "Deductible Expenses", "Net Income/Loss", "Net Land Class Income/Loss", "Combined Income/Loss", "Formation Loss Used", "Land Class Loss Brought Forward", "Land Class Loss amount to Carry Forward", "Land Class Loss claimed", "Taxable Income", "Taxable Loss", "Income/Loss not attributed Taxed @ Top PIR", "Income/Loss of Exited Zero-rate Investors", "Investor expenses less credits for fees", "Total Income To Attribute", "Total Loss To Attribute", "Income Attributed to 0% PIR", "Loss Attributed to 0% PIR", "Income Attributed to Low PIR", "Loss Attributed to Low PIR", "Income Attributed to Mid PIR", "Loss Attributed to Mid PIR", "Income Attributed to Top PIR", "Loss Attributed to Top PIR", "Tax Liability/Credit", "Zero-rated Exited Investor’s Tax payment for Exit Period", "Net Tax Liability/Credit", "Foreign Tax Credit", "Other Tax Credits", "Imputation Credit", "Resident Withholding Tax", "Income Attributed to NFI", "Tax paid on NFI Income"};
fieldNames["IR853_0003"] = {"PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total Number of Certificates", "Taxable Income/Loss", "Total Tax Credits used for low, mid and top PIR Investors", "PIE Tax Paid / Credited on Investor’s Income for low, mid and top PIR", "Taxable Income/Loss Taxed at low and/or mid rate(s)", "PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)", "Total Tax Credits on Investor’s income low and/or mid rate(s)", "Zero-rated Exited Investor Taxable Income / Loss", "Total Zero-rated Attributed Foreign Tax Credits", "Total Zero-rated Attributed Other /MAC Tax Credits", "Total Zero-rated Attributed IC Tax Credits", "Total Zero-rated Attributed RWT Tax Credits", "Zero-rated Exited Investor’s Tax payment for Exit Period"};
fieldNames["IR853_0004"] = {"PIE Return type", "Version Number", "PIE Name", "IR Number", "Period End Date", "Total Number of Certificates", "Total Income/Loss", "Total Tax Credits used", "PIE Tax Paid / Credited", "Taxable Income/Loss Taxed at low and/or mid rate(s)", "PIE Tax Paid / Credited on Investor’s Income at low and/or mid rate(s)", "Total Tax Credits on Investor’s income low and/or mid rate(s)", "Zero-rated Exited Investor Taxable Income / Loss", "Total Zero-rated Attributed Foreign Tax Credits", "Total Zero-rated Attributed Other /MAC Tax Credits", "Total Zero-rated Attributed IC Tax Credits", "Total Zero-rated Attributed RWT Tax Credits", "Zero-rated Exited Investor’s Tax payment for Exit Period"};
fieldNames["PIEC"] = {"Detail record indicator Parent", "PIE Return Type", "Version Number", "PIE Name", "PIE IR Number", "Period End Date", "Investor’s Name", "Investor’s IR Number", "Investor Certificate Identifier", "Prescribed Investor Rate (PIR) as at Year-end", "Was PIR changed during the year?", "Total Income/Loss", "Taxable Income/Loss", "PIE Tax Paid / Credited", "Foreign Tax Credits", "Other Tax Credits", "Imputation Credits", "Resident Withholding Tax", "Units Held at Year-end", "Country Code", "Address Line 1", "Address Line 2", "Address Line 3", "Post Code", "Country", "Email Address", "Phone Number", "Number of Joint Holders", "Joint Holder 1 Name", "Joint Holder 1 IR Number"};
fieldNames["PIEJ"] = {"Detail record indicator Joint", "Joint Holder Name", "Joint Holder IR Number"};
}
void read() {
std::ifstream file(filepath);
std::string line;
while (std::getline(file, line)) {
if (line.empty()) continue;
std::stringstream ss(line);
std::string field;
std::vector<std::string> fields;
while (std::getline(ss, field, ',')) {
fields.push_back(field);
}
std::string type = fields[0];
std::string version = fields.size() > 1 ? fields[1] : "";
std::string key = (type == "PIEC" || type == "PIEJ") ? type : type + "_" + version;
if (fieldNames.count(key) && fields.size() == fieldNames[key].size()) {
std::map<std::string, std::string> record;
for (size_t i = 0; i < fieldNames[key].size(); ++i) {
record[fieldNames[key][i]] = fields[i];
}
records.push_back(record);
}
}
}
void printProperties() {
read();
for (size_t i = 0; i < records.size(); ++i) {
std::cout << "Record " << (i + 1) << ":" << std::endl;
for (const auto& pair : records[i]) {
std::cout << " " << pair.first << ": " << pair.second << std::endl;
}
}
}
void write(const std::vector<std::map<std::string, std::string>>& newRecords) {
std::ofstream file(filepath);
for (const auto& record : newRecords) {
std::string type = record.count("PIE Return type") ? record.at("PIE Return type") : (record.count("Detail record indicator Parent") ? "PIEC" : "PIEJ");
std::string version = record.count("Version Number") ? record.at("Version Number") : "";
std::string key = (type == "PIEC" || type == "PIEJ") ? type : type + "_" + version;
if (fieldNames.count(key)) {
for (size_t i = 0; i < fieldNames[key].size(); ++i) {
auto it = record.find(fieldNames[key][i]);
file << (it != record.end() ? it->second : "") << (i < fieldNames[key].size() - 1 ? "," : "");
}
file << std::endl;
}
}
}
};
int main() {
PieFileHandler handler("example.pie");
handler.printProperties();
// handler.write({});
return 0;
}