// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";
contract RealState{
using SafeMath for uint;
address public contractOwner;
address public owner;
address public tenant;
//پورسانت صاحب قرار داد
uint public contractFee;
uint firstDeposit;
uint rentAmount;
uint startDate;
uint delayDates;
uint month = 1;
constructor(address _owner, uint _firstDeposit, uint _rentAmount, uint _contractFee){
contractOwner = _owner;
firstDeposit = _firstDeposit;
rentAmount = _rentAmount;
contractFee = _contractFee;
}
event paymentPaid (address indexed _Owner, address indexed Tenant, uint _Amount);
enum contractSate {NotStarted, Started, Ended, Suspanded}
contractSate state;
contractSate constant defaultState = contractSate.NotStarted;
//چک کردن هزینه اجاره هر ماه
modifier checkRentAmount(uint _amount){
require(_amount == rentAmount, "your money is not equal to rent payment");
_;
}
//چک کردن هزینه اولیه قرار داد
modifier checkInitialAmount(uint _amount){
require(_amount == firstDeposit, "your money is not equal to rent payment");
_;
}
modifier onlyTenant{
require(msg.sender == tenant && state == contractSate.Ended, "you cannot withdraw initial payment now !");
_;
}
modifier onlyOwner{
require(msg.sender == owner && address(this).balance==delayDates*0.01 ether, "you cannot call this function MAN !");
_;
}
//دیتای مربوط به پرداخت هر ماه
struct paidMonths{
uint _month;
uint _time;
uint _amount;
}
//ذخیره وضعیت هر ماه در مپیینگ
mapping(uint => paidMonths) public statusMonths;
//پرداخت مبلغ اولیه اجاره و مشخص کردن مستاجر و شروع قرار داد
function payInitialMoney(uint _amount) public payable checkInitialAmount(_amount){
tenant = msg.sender;
state = contractSate.Started;
startDate = block.timestamp;
emit paymentPaid(msg.sender, address(this), _amount);
}
//پرداخت ماهیانه اجاره ها
function payRent(uint _amount) public payable checkRentAmount(_amount){
//محاسبه کارمزد صاحب قرار داد
uint getContractFee = (address(this).balance.mul(contractFee)).div(100);
uint finalPayment = address(this).balance.sub(getContractFee);
//پرداخت کارمزد به صاحب قرار داد
payable(contractOwner).transfer(getContractFee);
payable(owner).transfer(finalPayment);
emit paymentPaid(msg.sender, owner, finalPayment);
if( month == 12 ){
state = contractSate.Ended;
delayDates = delayDates.add(block.timestamp-(firstDeposit + 35 days))/86400;
paidMonths memory newPayment = paidMonths(month, block.timestamp, _amount);
statusMonths[month] = newPayment;
} else{
delayDates = delayDates.add(block.timestamp-(firstDeposit + 35 days))/86400;
paidMonths memory newPayment = paidMonths(month, block.timestamp, _amount);
statusMonths[month] = newPayment;
month = month.add(1);
}
}
//برداشت پول اولیه
function withdrawInitialPayment() public onlyTenant{
uint remainingDeposit = address(this).balance.sub(delayDates*0.01 ether);
payable(tenant).transfer(remainingDeposit);
emit paymentPaid(address(this), tenant, remainingDeposit);
payable(owner).transfer(delayDates*0.01 ether);
emit paymentPaid(address(this), owner, delayDates*0.01 ether);
}
//کنسل شن قرار داد
function cancellContractByOwner() public onlyOwner{
payable(owner).transfer(address(this).balance);
emit paymentPaid(address(this), owner, address(this).balance);
state = contractSate.Suspanded;
}
}