398 lines
11 KiB
Solidity
398 lines
11 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.27;
|
|
|
|
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
|
|
|
contract ProjectToken is ERC20 {
|
|
using Strings for uint256;
|
|
|
|
constructor() ERC20("ProjectToken", "PTKN") {}
|
|
|
|
struct TokenDetail {
|
|
string tokenId;
|
|
string idProjek;
|
|
string idUser;
|
|
int256 nilai; // Changed to int256
|
|
}
|
|
|
|
struct Transaksi {
|
|
string idUser;
|
|
string namaUser;
|
|
string idProjek;
|
|
string judulProjek;
|
|
string ownerProjek;
|
|
int256 jumlahToken; // Changed to int256
|
|
int256 totalNominal; // Changed to int256
|
|
}
|
|
struct Agreement {
|
|
string idProjek;
|
|
string idUser;
|
|
string namaProyek;
|
|
string namaPetugas;
|
|
string alamatPetugas;
|
|
string namaPemilikProyek;
|
|
string nik;
|
|
string noHp;
|
|
string alamat;
|
|
string signature;
|
|
string tandaTangan;
|
|
int256 nominalDisetujui; // Changed to int256
|
|
uint256 createdAt;
|
|
}
|
|
|
|
mapping(uint256 => Agreement) public agreements;
|
|
uint256 public agreementCount;
|
|
|
|
event AgreementCreated(
|
|
string idProjek,
|
|
string idUser,
|
|
string namaProyek,
|
|
string namaPetugas,
|
|
string alamatPetugas,
|
|
string namaPemilikProyek,
|
|
string nik,
|
|
string noHp,
|
|
string alamat,
|
|
string signature,
|
|
string tandaTangan,
|
|
int256 nominalDisetujui,
|
|
uint256 createdAt
|
|
);
|
|
|
|
mapping(string => TokenDetail) public tokenDetails;
|
|
|
|
uint256 private tokenIdCounter;
|
|
|
|
string[] public allTokenIds;
|
|
|
|
event TokenCreated(
|
|
string indexed tokenId,
|
|
string idProjek,
|
|
string idUser,
|
|
int256 nilai
|
|
);
|
|
event TokenNominalReset(string indexed tokenId);
|
|
|
|
Transaksi[] public transaksiList;
|
|
|
|
function generateUniqueId() private returns (string memory) {
|
|
tokenIdCounter += 1;
|
|
uint256 counter = tokenIdCounter;
|
|
return
|
|
string(
|
|
abi.encodePacked(
|
|
"TKN-",
|
|
block.timestamp.toString(),
|
|
"-",
|
|
counter.toString()
|
|
)
|
|
);
|
|
}
|
|
|
|
function createToken(
|
|
string memory idProjek,
|
|
string memory idUser,
|
|
int256 nilai
|
|
) public {
|
|
string memory tokenId = generateUniqueId();
|
|
|
|
_mint(msg.sender, uint256(nilai >= 0 ? nilai : -nilai));
|
|
|
|
tokenDetails[tokenId] = TokenDetail(tokenId, idProjek, idUser, nilai);
|
|
allTokenIds.push(tokenId);
|
|
|
|
emit TokenCreated(tokenId, idProjek, idUser, nilai);
|
|
}
|
|
|
|
function getAllTokens() public view returns (TokenDetail[] memory) {
|
|
TokenDetail[] memory tokens = new TokenDetail[](allTokenIds.length);
|
|
|
|
for (uint256 i = 0; i < allTokenIds.length; i++) {
|
|
tokens[i] = tokenDetails[allTokenIds[i]];
|
|
}
|
|
|
|
return tokens;
|
|
}
|
|
|
|
function getTokenById(
|
|
string memory tokenId
|
|
) public view returns (TokenDetail memory) {
|
|
require(
|
|
bytes(tokenDetails[tokenId].tokenId).length > 0,
|
|
"Project Token not found"
|
|
);
|
|
return tokenDetails[tokenId];
|
|
}
|
|
|
|
function getTokenByProjectId(
|
|
string memory idProjek
|
|
) public view returns (TokenDetail[] memory) {
|
|
uint256 count = 0;
|
|
for (uint256 i = 0; i < allTokenIds.length; i++) {
|
|
if (
|
|
keccak256(bytes(tokenDetails[allTokenIds[i]].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
TokenDetail[] memory projekTokens = new TokenDetail[](count);
|
|
|
|
uint256 index = 0;
|
|
for (uint256 i = 0; i < allTokenIds.length; i++) {
|
|
if (
|
|
keccak256(bytes(tokenDetails[allTokenIds[i]].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
projekTokens[index] = tokenDetails[allTokenIds[i]];
|
|
index++;
|
|
}
|
|
}
|
|
|
|
return projekTokens;
|
|
}
|
|
|
|
function getTokenByUserAndProject(
|
|
string memory idUser,
|
|
string memory idProjek
|
|
) public view returns (TokenDetail[] memory) {
|
|
uint256 count = 0;
|
|
for (uint256 i = 0; i < allTokenIds.length; i++) {
|
|
if (
|
|
keccak256(bytes(tokenDetails[allTokenIds[i]].idUser)) ==
|
|
keccak256(bytes(idUser)) &&
|
|
keccak256(bytes(tokenDetails[allTokenIds[i]].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
TokenDetail[] memory filteredTokens = new TokenDetail[](count);
|
|
|
|
uint256 index = 0;
|
|
for (uint256 i = 0; i < allTokenIds.length; i++) {
|
|
if (
|
|
keccak256(bytes(tokenDetails[allTokenIds[i]].idUser)) ==
|
|
keccak256(bytes(idUser)) &&
|
|
keccak256(bytes(tokenDetails[allTokenIds[i]].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
filteredTokens[index] = tokenDetails[allTokenIds[i]];
|
|
index++;
|
|
}
|
|
}
|
|
|
|
return filteredTokens;
|
|
}
|
|
|
|
function getTotalTokens() public view returns (uint256) {
|
|
return allTokenIds.length;
|
|
}
|
|
|
|
function resetTokenNominal(string memory tokenId) public {
|
|
require(
|
|
bytes(tokenDetails[tokenId].tokenId).length > 0,
|
|
"Project Token not found"
|
|
);
|
|
|
|
int256 currentValue = tokenDetails[tokenId].nilai;
|
|
tokenDetails[tokenId].nilai = 0;
|
|
|
|
_burn(msg.sender, uint256(currentValue >= 0 ? currentValue : -currentValue));
|
|
|
|
emit TokenNominalReset(tokenId);
|
|
}
|
|
|
|
function addTransaction(
|
|
string memory idUser,
|
|
string memory namaUser,
|
|
string memory idProjek,
|
|
string memory judulProjek,
|
|
string memory ownerProjek,
|
|
int256 jumlahToken,
|
|
int256 totalNominal
|
|
) public {
|
|
transaksiList.push(
|
|
Transaksi({
|
|
idUser: idUser,
|
|
namaUser: namaUser,
|
|
idProjek: idProjek,
|
|
judulProjek: judulProjek,
|
|
ownerProjek: ownerProjek,
|
|
jumlahToken: jumlahToken,
|
|
totalNominal: totalNominal
|
|
})
|
|
);
|
|
}
|
|
|
|
function getAllTransaction() public view returns (Transaksi[] memory) {
|
|
return transaksiList;
|
|
}
|
|
|
|
function getTransactionByUserId(
|
|
string memory idUser
|
|
) public view returns (Transaksi[] memory) {
|
|
uint256 count = 0;
|
|
for (uint256 i = 0; i < transaksiList.length; i++) {
|
|
if (
|
|
keccak256(bytes(transaksiList[i].idUser)) ==
|
|
keccak256(bytes(idUser))
|
|
) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
Transaksi[] memory userTransactions = new Transaksi[](count);
|
|
uint256 index = 0;
|
|
|
|
for (uint256 i = 0; i < transaksiList.length; i++) {
|
|
if (
|
|
keccak256(bytes(transaksiList[i].idUser)) ==
|
|
keccak256(bytes(idUser))
|
|
) {
|
|
userTransactions[index] = transaksiList[i];
|
|
index++;
|
|
}
|
|
}
|
|
|
|
return userTransactions;
|
|
}
|
|
|
|
function getTransactionByProjectId(
|
|
string memory idProjek
|
|
) public view returns (Transaksi[] memory) {
|
|
uint256 count = 0;
|
|
for (uint256 i = 0; i < transaksiList.length; i++) {
|
|
if (
|
|
keccak256(bytes(transaksiList[i].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
Transaksi[] memory projectTransactions = new Transaksi[](count);
|
|
uint256 index = 0;
|
|
|
|
for (uint256 i = 0; i < transaksiList.length; i++) {
|
|
if (
|
|
keccak256(bytes(transaksiList[i].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
projectTransactions[index] = transaksiList[i];
|
|
index++;
|
|
}
|
|
}
|
|
|
|
return projectTransactions;
|
|
}
|
|
|
|
function createAgreementLetter(
|
|
string memory _idProjek,
|
|
string memory _idUser,
|
|
string memory _namaProyek,
|
|
string memory _namaPetugas,
|
|
string memory _alamatPetugas,
|
|
string memory _namaPemilikProyek,
|
|
string memory _nik,
|
|
string memory _noHp,
|
|
string memory _alamat,
|
|
string memory _signature,
|
|
string memory _tandaTangan,
|
|
int256 _nominalDisetujui
|
|
) public {
|
|
agreementCount++;
|
|
|
|
agreements[agreementCount] = Agreement({
|
|
idProjek: _idProjek,
|
|
idUser: _idUser,
|
|
namaProyek: _namaProyek,
|
|
namaPetugas: _namaPetugas,
|
|
alamatPetugas: _alamatPetugas,
|
|
namaPemilikProyek: _namaPemilikProyek,
|
|
nik: _nik,
|
|
noHp: _noHp,
|
|
alamat: _alamat,
|
|
signature: _signature,
|
|
tandaTangan: _tandaTangan,
|
|
nominalDisetujui: _nominalDisetujui,
|
|
createdAt: block.timestamp
|
|
});
|
|
|
|
emit AgreementCreated(
|
|
_idProjek,
|
|
_idUser,
|
|
_namaProyek,
|
|
_namaPetugas,
|
|
_alamatPetugas,
|
|
_namaPemilikProyek,
|
|
_nik,
|
|
_noHp,
|
|
_alamat,
|
|
_signature,
|
|
_tandaTangan,
|
|
_nominalDisetujui,
|
|
block.timestamp
|
|
);
|
|
}
|
|
|
|
function getAllAgreement() public view returns (Agreement[] memory) {
|
|
Agreement[] memory allAgreements = new Agreement[](agreementCount);
|
|
for (uint256 i = 1; i <= agreementCount; i++) {
|
|
allAgreements[i - 1] = agreements[i];
|
|
}
|
|
return allAgreements;
|
|
}
|
|
|
|
function getAgreementByProjectId(
|
|
string memory idProjek
|
|
) public view returns (Agreement[] memory) {
|
|
uint256 count = 0;
|
|
for (uint256 i = 1; i <= agreementCount; i++) {
|
|
if (
|
|
keccak256(bytes(agreements[i].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
Agreement[] memory projectAgreements = new Agreement[](count);
|
|
uint256 index = 0;
|
|
for (uint256 i = 1; i <= agreementCount; i++) {
|
|
if (
|
|
keccak256(bytes(agreements[i].idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
projectAgreements[index] = agreements[i];
|
|
index++;
|
|
}
|
|
}
|
|
|
|
return projectAgreements;
|
|
}
|
|
|
|
function getTotalNominalToken(
|
|
string memory idUser,
|
|
string memory idProjek
|
|
) public view returns (int256) { // Changed to int256
|
|
int256 totalNominal = 0; // Changed to int256
|
|
|
|
for (uint256 i = 0; i < allTokenIds.length; i++) {
|
|
TokenDetail memory tokenDetail = tokenDetails[allTokenIds[i]];
|
|
if (
|
|
keccak256(bytes(tokenDetail.idUser)) ==
|
|
keccak256(bytes(idUser)) &&
|
|
keccak256(bytes(tokenDetail.idProjek)) ==
|
|
keccak256(bytes(idProjek))
|
|
) {
|
|
totalNominal += tokenDetail.nilai;
|
|
}
|
|
}
|
|
|
|
return totalNominal;
|
|
}
|
|
} |