Experiment with Rust
syntax = "proto3";

package rfkpos;

service RFKPOS {
    rpc Create(CreateTransaction) returns (TransactionReturn);
    rpc Get(GetTransaction) returns (TransactionReturn);
}

message GetTransaction {
    string token = 1;
    optional uint64 tid = 2;
    optional string signature = 99;
}

message CreateTransaction {
    string token = 1;
    Transaction transaction = 2;
    optional string signature = 99;
}

enum Currency {
    EUR = 0;
    USD = 1;
    NOK = 2;
    BTC = 3;
    LTN = 4;
    ETH = 5;
    DOT = 6;
}

message Money {
    int64 value = 1;
    uint64 dec = 2;
    Currency cur = 3;
}

message Timestamp {
    uint32 year = 1;
    uint32 month = 2;
    uint32 day = 3;
    uint32 hour = 4;
    uint32 minute = 5;
    uint32 second = 6;
    int32 tz = 7;
}

enum Units {
    U_D = 0; // discrete
    U_G = 1; // gram
    U_M = 2; // metre
    U_L = 3; // litre
}

message Usage {
    double amount = 1;
    uint64 item = 2;
    optional string comment = 3;
}

message Product {
    string name = 1;
    Money price = 2; // default price to use
    Units units = 3;
    bool to_sell = 10;
    bool to_buy = 11;
    bool need_date_from = 12;
    bool need_date_to = 13;
    map<string, string> identifiers = 14; // key is system name and value is identifier in that system
    optional string comment = 40;
    repeated Usage usage = 50;
    repeated string tag = 51; // product is shown in different places depending on tag
    repeated uint64 invalidates = 90; // tid's of products to invalidate
}

message PurchaseEntry {
    uint64 product = 1;
    double amount = 2;
    Money price = 3;
    optional Money discount = 4;
    optional Timestamp valid_from = 5;
    optional Timestamp valid_to = 6;
}

enum PurchaseType {
    P_SELL = 0;
    P_BUY = 1;
    P_RENT = 2;
    P_INVALIDATE = 3;
}

message Purchase {
    Timestamp ts = 1;
    PurchaseType purchase_type = 2;
    optional Timestamp valid_until = 3;
    optional uint64 customer = 4; // customer tid
    optional Money discount = 5;
    repeated PurchaseEntry entry = 6;
    repeated uint64 invalidate = 7; // tid of transaction to invalidate
    optional string comment = 8;
}

enum PaymentType {
    PAY_CASH = 0;
    PAY_CARD = 1;
    PAY_CRYPTO = 3;
    PAY_PAYPAL = 4;
    PAY_VIPS = 5;
}

message Payment {
    PaymentType type = 1;
    Money amount = 2;
    Timestamp ts = 3;
    optional uint64 customer = 4; // tid of the customer payed
}

message Customer {
    string name = 1;
    string address = 2;
    map<string, string> identifiers = 3; // identifers of that customer in different systems
    optional string comment = 4;
    repeated string tags = 5;
}

message User {
    string name = 1;
    string public_key = 2;
}

message Transaction {
    uint64 tid = 1;
    uint64 parent = 2; // tid of the parent transaction
    uint64 uid = 3; // tid of the user transaction
    uint64 ts = 4; // unix time in seconds
    oneof transaction_type {
        Purchase purchase = 10;
        Customer customer = 20;
        Product product = 21;
        Payment payment = 30;
        User user = 90;
    }
    optional string signature = 99;
}

message TransactionReturn {
    string token = 1;
    uint64 tid = 2;
}

message Database {
    uint64 next_tid = 1;
    map<uint64, Transaction> transactions = 2;
}