Skip to content

Instantly share code, notes, and snippets.

@ajoydas
Last active August 4, 2019 00:36
Show Gist options
  • Save ajoydas/c77838dde19977c1fa2b4b467ed8a10f to your computer and use it in GitHub Desktop.
Save ajoydas/c77838dde19977c1fa2b4b467ed8a10f to your computer and use it in GitHub Desktop.
pragma solidity ^0.5.7;
pragma experimental ABIEncoderV2;
// import "github.com/ethereum/dapp-bin/library/stringUtils.sol";
contract Foodie {
struct Item {
string name;
uint256 price;
bool disabled;
}
struct Restaurant {
address payable owner;
uint256 fund;
string name;
string addr;
uint256 areaId;
uint256 itemId;
mapping(uint256=> Item) items;
// Item[] items;
}
struct User {
string name;
string addr;
uint256 phoneNo;
}
struct Order {
address payable orderer;
address payable deliverer;
uint256 fund;
uint256 restaurantId;
uint256[] items;
uint256[] quantities;
uint256 areaId;
string fullAddress;
bool isCanceled;
bool restaurantApproved;
bool pickupConfirmed;
bool orderReceived;
bool reclaimed;
uint256 orderTime;
}
// Admin methods
address admin = msg.sender;
string[] areas;
uint commissionRate = 10;
uint lockedRate = 50;
uint256 deliveryFee = 100;
uint maxDeliveryTime = 60;
modifier isAdmin() {
require(msg.sender == admin);
_;
}
function addArea(string memory area) public isAdmin {
// require(!checkAreaExists(area), "Area already exists.");
areas.push(area);
}
function getArea(uint256 id) public view returns(string memory area){
return areas[id];
}
function getAreas() public view returns(string[] memory){
return areas;
}
// function checkAreaExists(string memory area) private view returns(bool found){
// for (uint i=0; i<areas.length; i++) {
// if(StringUtils.equal(areas[i], area)) return true;
// }
// return false;
// }
// Restaurant methods
// mapping(uint256 => Restaurant) restaurants;
Restaurant[] restaurants;
uint256 restaurantId;
function addRestaurant(string memory name, string memory addr, uint256 areaId)
public payable {
Restaurant memory restaurant;
restaurant.owner = msg.sender;
require(msg.value > 0);
restaurant.fund = msg.value;
restaurant.name = name;
restaurant.addr = addr;
restaurant.areaId = areaId;
restaurants.push(restaurant);
// event
emit newRestaurant(restaurants.length -1);
}
function getRestaurant(uint256 id) public view
returns(string memory name, string memory addr, uint256 areaId, uint256 itemCount) {
Restaurant storage restaurant = restaurants[id];
return (restaurant.name, restaurant.addr, restaurant.areaId, restaurant.itemId);
}
function addItem(uint256 id, string memory name, uint256 price) public {
Restaurant storage restaurant = restaurants[id];
require(restaurant.owner == msg.sender);
restaurant.items[restaurant.itemId] = Item(name, price, false);
restaurant.itemId++;
}
function getItem(uint256 restId, uint256 itemId) public view
returns (string memory name, uint256 price){
Item storage item = restaurants[restId].items[itemId];
return (item.name, item.price);
}
// User mathods
mapping(address => User) users;
function register(string memory name, string memory addr, uint256 phoneNo) public {
User memory user = User(name, addr, phoneNo);
users[msg.sender] = user;
}
// Orderer methods
Order[] orders;
function placeOrder(uint256[] memory items, uint256[] memory quantities, uint256 areaId,
string memory fullAddress, uint256 restId) public payable {
// add requires
Order memory order;
order.orderer = msg.sender;
order.items = items;
order.quantities = quantities;
order.areaId = areaId;
order.fullAddress = fullAddress;
Restaurant storage restaurant = restaurants[restId];
require(restaurantIsAvailable(restaurant, order.fund), "Restaurant is unable to deliver");
order.restaurantId = restId;
// calculate prices
uint256 price = 0;
for(uint i=0; i <items.length; i++){
price += restaurants[restId].items[items[i]].price * quantities[i];
}
require(msg.value == price + deliveryFee , "Not enough fund sent.");
order.fund = price;
order.orderTime = now;
orders.push(order);
//event
emit newOrder(orders.length -1, restaurant.owner);
}
function getRestaurantOrders() public view returns(Order[] memory){
uint256 totalMatch = 0;
for(uint256 i=0; i< orders.length; i++){
Order storage order = orders[i];
Restaurant storage restaurant = restaurants[order.restaurantId];
if(restaurant.owner == msg.sender && !order.isCanceled && !order.orderReceived){
totalMatch++;
}
}
totalMatch = 0;
Order[] memory selected = new Order[](totalMatch);
for(uint256 i=0; i< orders.length; i++){
Order storage order = orders[i];
Restaurant storage restaurant = restaurants[order.restaurantId];
if(restaurant.owner == msg.sender && !order.isCanceled && !order.orderReceived){
selected[totalMatch] = order;
totalMatch++;
}
}
return selected;
}
function getDelivererOrders() public view
returns(uint256[] memory){
uint256 totalMatch = 0;
for(uint256 i=0; i< orders.length; i++){
Order storage order = orders[i];
if(order.deliverer == msg.sender && !order.orderReceived){
totalMatch++;
}
}
totalMatch = 0;
uint256[] memory selected = new uint256[](totalMatch);
for(uint256 i=0; i< orders.length; i++){
Order storage order = orders[i];
if(order.deliverer == msg.sender && !order.orderReceived){
selected[totalMatch] = i;
totalMatch++;
}
}
return selected;
}
function getDelivererOrder(uint256 orderId) public view
returns(uint256[] memory, uint256[] memory, uint256, string memory,
uint256, string memory, uint256, bool, bool){
Order storage order = orders[orderId];
uint256 phoneNo = 0;
string memory name = users[order.orderer].name;
if(order.deliverer == msg.sender){
phoneNo = users[order.orderer].phoneNo;
}
return (order.items, order.quantities, order.fund, order.fullAddress,
order.areaId, name, phoneNo, order.pickupConfirmed, order.orderReceived);
}
function getOrdererOrders() public view returns(Order[] memory){
uint256 totalMatch = 0;
for(uint256 i=0; i< orders.length; i++){
Order storage order = orders[i];
if(order.orderer == msg.sender && !order.isCanceled && !order.orderReceived){
totalMatch++;
}
}
totalMatch = 0;
Order[] memory selected = new Order[](totalMatch);
for(uint256 i=0; i< orders.length; i++){
Order storage order = orders[i];
if(order.orderer == msg.sender && !order.isCanceled && !order.orderReceived){
selected[totalMatch] = order;
totalMatch++;
}
}
return selected;
}
function cancelOrder(uint256 orderId) public {
Order storage order = orders[orderId];
require(order.orderer == msg.sender && !order.isCanceled
&& order.deliverer != address(0));
order.isCanceled = true;
// transfer fund
msg.sender.transfer(order.fund + deliveryFee);
if(order.restaurantApproved){
// unlock deliverer commission
Restaurant storage restaurant = restaurants[order.restaurantId];
restaurant.owner.transfer(calculateCommission(order.fund));
}
// event
emit orderCanceled(orderId, order.orderer);
}
function receiveOrder(uint256 orderId) public {
Order storage order = orders[orderId];
require(order.orderer == msg.sender);
require(!order.orderReceived && !order.isCanceled && order.deliverer != address(0));
order.orderReceived = true;
order.fund = 0;
// transfer
uint256 commission = calculateCommission(order.fund);
order.deliverer.transfer(order.fund + (order.fund/100) * lockedRate + deliveryFee + commission);
}
function approveOrder(uint256 orderId) public {
Order storage order = orders[orderId];
Restaurant storage restaurant = restaurants[order.restaurantId];
require(restaurant.owner == msg.sender);
order.restaurantApproved = true;
// lock deliverer commission
restaurant.fund -= calculateCommission(order.fund);
// event
emit orderApproved(orderId, order.orderer);
}
function calculateCommission(uint256 fund) private view returns(uint256){
return (fund/100)* commissionRate;
}
function searchAreaRestaurant(uint256 areaId) public view
returns(uint256[] memory, string[] memory, string[] memory) {
uint256 totalMatch = 0;
for(uint256 i=0; i<restaurants.length; i++){
Restaurant storage restaurant = restaurants[i];
if(restaurant.areaId == areaId && restaurantIsAvailable(restaurant, 100)){
totalMatch++;
}
}
uint256[] memory restIds = new uint256[](totalMatch);
string[] memory names = new string[](totalMatch);
string[] memory fullAddrs = new string[](totalMatch);
totalMatch = 0;
for(uint256 i=0; i<restaurants.length; i++){
Restaurant storage restaurant = restaurants[i];
if(restaurant.areaId == areaId && restaurantIsAvailable(restaurant, 100)){
restIds[totalMatch] = i;
names[totalMatch] = restaurant.name;
fullAddrs[totalMatch] = restaurant.addr;
totalMatch++;
}
}
return(restIds, names, fullAddrs);
}
function restaurantIsAvailable(Restaurant memory restaurant, uint256 price) private view returns(bool){
return restaurant.fund >= (price/100)* commissionRate;
}
function reclaim(uint256 orderId) public {
Order storage order = orders[orderId];
require(msg.sender == order.orderer, "Access rejected.");
require(!order.isCanceled && !order.orderReceived &&
!order.reclaimed, "Invalid reclaim request.");
require(order.orderTime + maxDeliveryTime * 1 minutes < now, "Try after max order duration.");
uint256 ordererAmount = (order.fund/100) * lockedRate + order.fund + deliveryFee; // deliverer locked + oderer locked.
order.orderer.transfer(ordererAmount);
if(order.restaurantApproved){
// unlock deliverer commission
Restaurant storage restaurant = restaurants[order.restaurantId];
restaurant.owner.transfer(calculateCommission(order.fund));
}
if(order.deliverer == address(0)){
order.deliverer.transfer(order.fund);
}
order.fund = 0;
order.reclaimed = true;
}
// Deliverer methods
function orderIsAvailable(Order memory order) private pure returns(bool){
return order.restaurantApproved
&& order.deliverer == address(0) && !order.isCanceled;
}
function searchAreaOrder(uint256 areaId) public view
returns(uint256[] memory, address[] memory, string[] memory, uint256[] memory){
uint256 totalMatch = 0;
for(uint256 i=0; i<orders.length; i++){
Order storage order = orders[i];
if(order.areaId == areaId && orderIsAvailable(order)){
totalMatch++;
}
}
uint256[] memory orderIds = new uint256[](totalMatch);
address[] memory orderers = new address[](totalMatch);
string[] memory fullAddrs = new string[](totalMatch);
uint256[] memory prices = new uint256[](totalMatch);
totalMatch = 0;
for(uint256 i=0; i<orders.length; i++){
Order storage order = orders[i];
if(order.areaId == areaId && orderIsAvailable(order)){
orderIds[totalMatch] =i;
orderers[totalMatch] = order.orderer;
fullAddrs[totalMatch] = order.fullAddress;
prices[totalMatch] = order.fund;
totalMatch++;
}
}
return (orderIds, orderers, fullAddrs, prices);
}
function acceptOrder(uint256 orderId) public payable {
Order storage order = orders[orderId];
require(orderIsAvailable(order));
uint256 expected = order.fund + (order.fund/100)* lockedRate;
require(msg.value == expected, "Not enough fund given.");
order.deliverer = msg.sender;
// event
Restaurant storage restaurant = restaurants[order.restaurantId];
emit orderAccepted(orderId, order.deliverer, restaurant.owner);
}
function confirmPickup(uint256 orderId) public {
Order storage order = orders[orderId];
require(msg.sender == order.deliverer, "Access rejected.");
require(!order.isCanceled && order.restaurantApproved && !order.pickupConfirmed, "Invalid request.");
order.pickupConfirmed = true;
Restaurant storage restaurant = restaurants[order.restaurantId];
restaurant.owner.transfer(order.fund);
// event
emit orderPickedup(orderId, order.orderer);
}
event newRestaurant(uint256 restaurantId);
event newOrder(uint256 orderId, address restaurant);
event orderCanceled(uint256 orderId, address orderer);
event orderApproved(uint256 orderId, address orderer);
event orderAccepted(uint256 orderId, address deliverer, address restaurant);
event orderPickedup(uint256 orderId, address orderer);
// event orderDelivered(uint256 orderId, address orderer);
function genEvent(uint option) public {
if(option == 0){
emit newRestaurant(0);
} else if(option == 1){
emit newOrder(0, 0x02d91Ba6b954cfA50b2Dd685212dAE7Cf26B52B9);
} else if (option == 2){
emit orderCanceled(0, 0x7E3d972A5916B6dD9b3d518BF8f36D891CECB910);
} else if (option == 3){
emit orderApproved(0, 0x7E3d972A5916B6dD9b3d518BF8f36D891CECB910);
} else if(option == 4){
emit orderAccepted(0, 0xbfb21c004EEDc4229d30485E09fcA941eB76223A, 0x02d91Ba6b954cfA50b2Dd685212dAE7Cf26B52B9);
} else if(option == 5){
emit orderPickedup(0, 0x7E3d972A5916B6dD9b3d518BF8f36D891CECB910);
}
// else if(option == 5){
// emit orderDelivered(0, 0x7E3d972A5916B6dD9b3d518BF8f36D891CECB910);
// }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment