couponctr
unknown
c_cpp
3 years ago
6.7 kB
13
Indexable
#include "couponctr.hpp"
#include <eosio/eosio.hpp>
#include <string>
using namespace std;
using namespace eosio;
/*
ISSUE
Questa azione permette ad un produttore di emettere un nuovo coupon.
Input: Tipo del coupon ('a' valore sconto fisso, 'p' valore sconto percentuale), valore del coupon,
data di scadenza, address del consumatore a cui sarà assegnato il coupon.
Permessi: producerp */
[[eosio::action]] void couponctr::issue(const string coupon_type,
const float coupon_value,
const string expiration,
const eosio::name consumer)
{
check(!coupon_type.compare("a") || !coupon_type.compare("p"), "Coupon type must be 'a' for absolute value or 'p' for percentage value.");
std::string s(expiration);
struct tm tm
{
};
strptime(s.c_str(), "%d-%m-%Y", &tm);
time_t t = mktime(&tm);
coupon_table c_t("couponctr"_n, "couponctr"_n.value);
c_t.emplace("producer"_n, [&](auto &c)
{
c.coupon_id = c_t.available_primary_key();
c.coupon_type = coupon_type;
c.producer = current_receiver(); // current_reicever returns the account which specifies the current receiver of the action
c.consumer = consumer;
c.creation = time(0); // current date/time based on current system
c.expiration = t;
c.coupon_value = coupon_value;
c.isValid = true; });
}
/*La funzione acquire per ora è messa da parte perché EOSIO non permette di avere un parametro di tipo 'name' come opzionale (non è
possibile avere un name nullo) ed inoltre non è possibile avere overloading di azioni, per cui bisognerebbe creare un'azione extra
solo per creare coupon non assegnati, questi coupon dovrebbero appartenere ad una tabella diversa e in caso di acquisto dovrebbero
essere convertiti al primo tipo di coupon (quelli assegnati) e riaggiunti alla prima tabella. Conviene mantenere fede al modello o
rivederlo eliminando i coupon non assegnati? Per ora io sono per la seconda opzione, i coupon non assegnati erano stati inseriti per
rendere il modello più generale possibile, però nel pratico difficilmente verrebbero implementati.
[[eosio::action]] void couponctr::acquire(const uint64_t coupon_id,
const name consumer)
{
coupon_table c_t("couponctr"_n, "couponctr"_n.value);
auto c_itr = c_t.find(coupon_id);
check(c_itr != c_t.end(), "Coupon ID not found.");
require_auth(consumer);
check(c_itr->consumer.value != NULL, "Coupon is already assigned.");
c_t.modify(c_itr, consumer, [&](auto &c)
{ c.consumer = consumer; });
}*/
/* TRANSFER
Azione con cui un consumatore trasferisce un proprio coupon ad un altro utente.
Input: id del coupon da trasferire, address dell'utente destinatario.
Permessi: consumerp */
[[eosio::action]] void couponctr::transfer(const uint64_t coupon_id,
const name consumer1, const name consumer2)
{
coupon_table c_t("couponctr"_n, "couponctr"_n.value);
auto c_itr = c_t.find(coupon_id);
check(c_itr != c_t.end(), "Coupon ID not found.");
check(c_itr->isValid == true, "Coupon has already been redeemed.");
require_auth(consumer1);
c_t.modify(c_itr, consumer1, [&](auto &c)
{
check (c.consumer == consumer1, "Coupon is assigned to another consumer.");
c.consumer = consumer2; });
}
/* INVALIDATE
Azione con cui si cancella un coupon rendendolo non più valido.
Input: id del coupon da cancellare
Permessi: interp (intermediario)*/
[[eosio::action]] void couponctr::invalidate(const uint64_t coupon_id)
{
coupon_table c_t("couponctr"_n, "couponctr"_n.value);
auto c_itr = c_t.find(coupon_id);
check(c_itr != c_t.end(), "Coupon ID not found.");
name user;
if (has_auth("producer"_n))
{
user = "producer"_n;
}
if (has_auth("intermediary"_n))
{
user = "intermediary"_n;
}
c_t.modify(c_itr, user, [&](auto &c)
{ c.isValid = false; });
// c_t.erase(c_itr); la funzione erase cancella del tutto il coupon, può essere utile invece mantenerlo e dare come feedback il fatto che non sia valido
}
/* REDEEM
Azione con cui viene riscattato un coupon.
Input: id del coupon da riscattare, importo della transazione in atto.
[ATTENZIONE: l'importo della transazione viene ottenuto dalla transazione in atto durante il riscatto del coupon, per ora si sottindende che ci sia
un sistema che faccia sì che ciò avvenga].
Output: il nuovo importo calcolato secondo tipo e valore del coupon riscattato. Una volta riscattato un coupon non è più valido e viene cancellato.
Permessi: interp (intermediario) */
[[eosio::action]] float couponctr::redeem(const uint64_t coupon_id,
const float amount)
{
coupon_table c_t("couponctr"_n, "couponctr"_n.value);
auto c_itr = c_t.find(coupon_id);
check(c_itr != c_t.end(), "Coupon ID not found.");
check(c_itr->isValid == true, "Coupon has already been redeemed.");
/* Si verifica che il coupon corrispondente sia valido attraverso il valoredi isValid (che deve essere pari a 1) e il confronto tra la data
attuale e quella riportata in expiration, che specifica la data di scadenza*/
if (c_itr->expiration < time(0))
{
// Per sopperire al problema di conflitto tra la libreria time.h e alcune di eosio si stampano i due valori temporali, verrano visualizzati come pending output al momento dell'attivazione di check
print("Time ", time(0));
print(" Expiration ", c_itr->expiration);
invalidate(coupon_id);
// struct tm *exp = localtime(&c_itr->expiration); le funzioni della libreria time.h entrano in conflitto con altre librerie di eosio
// print("Coupon has expired ", std::asctime(exp));
check(c_itr->expiration > time(0), "Coupon has expired");
return amount;
}
print(c_itr->coupon_type);
/* Il tipo di coupon 'a' corrisponde ad un coupon sconto assoluto, cioè con un valore fisso*/
if (!c_itr->coupon_type.compare("a"))
{
float new_amount = amount - c_itr->coupon_value;
invalidate(coupon_id);
return new_amount;
}
/* L'altro tipo di coupon possibile è contrassegnato con 'p' e corrisponde ad un coupon dal valore percentuale*/
if (!c_itr->coupon_type.compare("p"))
{
float new_amount = amount - (amount * c_itr->coupon_value) / 100;
invalidate(coupon_id);
return new_amount;
}
return amount;
}Editor is loading...