couponctr

 avatar
unknown
c_cpp
2 years ago
6.7 kB
9
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...