Skip to content

Instantly share code, notes, and snippets.

@georgescumihai
Last active August 2, 2023 15:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save georgescumihai/8f6a490bad9256a52f8f77cb13f8bb0a to your computer and use it in GitHub Desktop.
Save georgescumihai/8f6a490bad9256a52f8f77cb13f8bb0a to your computer and use it in GitHub Desktop.
Calculator Taxation of VV
enum Constant {
static let igic: Double = 0.07
}
struct CostStructure {
let grossIncome: Double
let netIncome: Double
let otaCommission: Double
let managementCommission: Double
let cleaningAndSuppliesPerNight: Double
let igic: Double
var expenses: Double {
otaCommission + managementCommission + cleaningAndSuppliesPerNight
}
var igicForExpenses: Double {
expenses * Constant.igic
}
var igicToPay: Double {
let negativeIgic = igicForExpenses
let igicToPay = igic - negativeIgic
return igicToPay
}
}
struct Calculator {
let otaCommissionPercentage: Double
let managementCommissionPercentage: Double
let suppliesCostPerStay: Double
let cleaningCostPerStay: Double
func calculateDayRate(gross: Double, averageLength: UInt) -> CostStructure {
var income = gross
let otaCommission = calculateOTACCommission(income: gross)
// Remove OTA Comission
income -= otaCommission
let cleaningAndSuppliesCost = calculateCleaningAndSuppliesCost(averageLength: averageLength)
income -= cleaningAndSuppliesCost
let managementCommission = calculateManagementCommission(income: income)
income -= managementCommission
return CostStructure(
grossIncome: gross,
netIncome: income,
otaCommission: otaCommission,
managementCommission: managementCommission,
cleaningAndSuppliesPerNight: cleaningAndSuppliesCost,
igic: calculateIGIC(priceIncludingIGIC: gross)
)
}
func calculateDayRate(netIncome: Double, averageLength: UInt) -> CostStructure {
var income = netIncome
// Reverse Management Commission
income = income / (1 - managementCommissionPercentage / 100)
let managementCommission = income * managementCommissionPercentage / 100
// Add Cleaning and Supplies Cost
let cleaningAndSuppliesCost = (suppliesCostPerStay + cleaningCostPerStay) / Double(averageLength)
income += cleaningAndSuppliesCost
// Reverse OTA Commission
income = income / (1 - otaCommissionPercentage / 100)
let otaCommission = income * otaCommissionPercentage / 100
// IGIC
let grossIncome = income
let igic = calculateIGIC(priceIncludingIGIC: grossIncome)
return CostStructure(
grossIncome: grossIncome,
netIncome: netIncome,
otaCommission: otaCommission,
managementCommission: managementCommission,
cleaningAndSuppliesPerNight: cleaningAndSuppliesCost,
igic: igic
)
}
func calculateYearlyRate(
averageGrossDayRate: Double,
occupancy: Double,
averageLength: Double,
cleaningCost: Double
) -> CostStructure {
guard (0.0...1.0).contains(occupancy) else {
fatalError("Wrong occupancy")
}
let totalNumberOfNights = 365 * occupancy
let grossIncome = averageGrossDayRate * totalNumberOfNights
var income = grossIncome
let otaCommission = calculateOTACCommission(income: income)
// Remove OTA Comission
income -= otaCommission
var cleaningAndSuppliesCost = floor(totalNumberOfNights / averageLength) * cleaningCost
income -= cleaningAndSuppliesCost
let managementCommission = calculateManagementCommission(income: income)
income -= managementCommission
return CostStructure(
grossIncome: grossIncome,
netIncome: income,
otaCommission: otaCommission,
managementCommission: managementCommission,
cleaningAndSuppliesPerNight: cleaningAndSuppliesCost,
igic: calculateIGIC(priceIncludingIGIC: grossIncome)
)
}
private func calculateOTACCommission(income: Double) -> Double {
return income * otaCommissionPercentage / 100
}
private func calculateManagementCommission(income: Double) -> Double {
return income * managementCommissionPercentage / 100
}
private func calculateCleaningAndSuppliesCost(averageLength: UInt) -> Double {
return (suppliesCostPerStay + cleaningCostPerStay) / Double(averageLength)
}
private func calculateIGIC(priceIncludingIGIC: Double) -> Double {
let priceWithoutIGIC = priceIncludingIGIC / (1 + Constant.igic)
let igic = priceIncludingIGIC - priceWithoutIGIC
return igic
}
}
let standardCalculator = Calculator(
otaCommissionPercentage: 15,
managementCommissionPercentage: 18,
suppliesCostPerStay: 5,
cleaningCostPerStay: 50
)
let income = standardCalculator.calculateDayRate(gross: 166, averageLength: 5)
let incomeFromNet = standardCalculator.calculateDayRate(netIncome: 107, averageLength: 5)
extension NumberFormatter {
static let currencyFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencySymbol = "€"
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
return formatter
}()
static let percentageFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .percent
return formatter
}()
}
enum Printer {
static let currencyFormatter = NumberFormatter.currencyFormatter
static func logCost(_ cost: CostStructure) {
print(
"""
# Income details
Gross (Including IGIC): \(currencyFormatter.string(from: NSNumber(value: cost.grossIncome)) ?? "N/A")
Net (Including IGIC): \(currencyFormatter.string(from: NSNumber(value: cost.netIncome)) ?? "N/A")
Airbnb / Bookings (without IGIC): \(currencyFormatter.string(from: NSNumber(value: cost.otaCommission)) ?? "N/A")
Cleaning and supplies (without IGIC): \(currencyFormatter.string(from: NSNumber(value: cost.cleaningAndSuppliesPerNight)) ?? "N/A")
Pambnb Management (without IGIC): \(currencyFormatter.string(from: NSNumber(value: cost.managementCommission)) ?? "N/A")
IGIC on expenses: \(currencyFormatter.string(from: NSNumber(value: cost.igicForExpenses)) ?? "N/A")
IGIC to Pay: \(currencyFormatter.string(from: NSNumber(value: cost.igicToPay)) ?? "N/A")
## Total for owner (After IGIC was paid)
\(currencyFormatter.string(from: NSNumber(value: cost.netIncome - cost.igic)) ?? "N/A")
"""
)
}
}
func calculateYearly(
rates: [Double],
occupancy: Double,
averageLength: Double,
cleaningCost: Double,
monthlyUtilities: Double
) {
print("Occupancy \(NumberFormatter.percentageFormatter.string(from: NSNumber(value: occupancy))!)")
print("Average booking length \(averageLength) nights")
print("Cleaning and supply costs per booking \(NumberFormatter.currencyFormatter.string(from: NSNumber(value: cleaningCost))!)")
print("Monthly utilities (Electricity, Water, Internet, Cable): \(NumberFormatter.currencyFormatter.string(from: NSNumber(value: monthlyUtilities))!)")
rates.forEach {
let cost = standardCalculator.calculateYearlyRate(
averageGrossDayRate: $0,
occupancy: occupancy,
averageLength: averageLength,
cleaningCost: cleaningCost
)
if let dailyRate = NumberFormatter.currencyFormatter.string(from: NSNumber(value: $0)) {
print("\nAverageDailyRate: \(dailyRate)")
}
Printer.logCost(cost)
let yearlyUtilities = monthlyUtilities * 12
let incomeTaxNonResidentHisLicense = (cost.grossIncome - cost.igic) * 0.24
let incomeTaxNonResidentOurLicense = (cost.netIncome - cost.igic - yearlyUtilities) * 0.24
print("Income Tax NonResident 24% (Owner License) \(NumberFormatter.currencyFormatter.string(from: NSNumber(value: incomeTaxNonResidentHisLicense))!)")
print("Income Tax NonResident 24% (Pambnb License) \(NumberFormatter.currencyFormatter.string(from: NSNumber(value: incomeTaxNonResidentOurLicense))!)")
}
}
calculateYearly(rates: [70, 80, 90, 110], occupancy: 0.7, averageLength: 4, cleaningCost: 50, monthlyUtilities: 110)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment