Allow indicating recurring SEPA donations in payproc-post.
authorWerner Koch <wk@gnupg.org>
Mon, 12 Jun 2017 13:27:10 +0000 (15:27 +0200)
committerWerner Koch <wk@gnupg.org>
Mon, 12 Jun 2017 13:27:10 +0000 (15:27 +0200)
* src/commands.c (cmd_commitpreorder): Allow for 'Recur' parameter.
* src/preorder.c (preorder_update_record): Handle 'Recur'.  Allow
updating passed dictionary.  Store RECUR in the journal.
* src/payproc-post.c (send_request): Also print failure messages.
(post_sepa): Implement AMOUNT/RECUR syntax.
(listpreorder): Print full timestamp of last payment.

Signed-off-by: Werner Koch <wk@gnupg.org>
src/commands.c
src/payproc-post.c
src/preorder.c
src/preorder.h

index 8604f98..7009287 100644 (file)
@@ -960,6 +960,9 @@ cmd_sepapreorder (conn_t conn, char *args)
    Sepa-Ref:   The key referencing the preorder
    Amount:     The actual amount of the payment.
    Currency:   If given its value must be EUR.
+   Recur:      Optional: '*' indicates that the SEPA data indicates
+               a recurring donation of any kind.  Any other valid value
+               forces the use of that value.
 
    On success these items are returned:
 
@@ -976,6 +979,7 @@ cmd_commitpreorder (conn_t conn, char *args)
   keyvalue_t kv;
   const char *s;
   char *buf = NULL;
+  int recur = 0;
 
   (void)args;
 
@@ -986,6 +990,16 @@ cmd_commitpreorder (conn_t conn, char *args)
       goto leave;
     }
 
+  /* Check recurrance parameter  */
+  s = keyvalue_get_string (dict, "Recur");
+  if (!*s || !strcmp (s, "*"))
+    ; /* None or 'any kind'.  */
+  else if (!valid_recur_p (s, &recur))
+    {
+      set_error (MISSING_VALUE, "Invalid value for 'Recur'");
+      goto leave;
+    }
+
   /* Get currency and amount.  */
   s = keyvalue_get (dict, "Currency");
   if (!s)
@@ -1022,7 +1036,7 @@ cmd_commitpreorder (conn_t conn, char *args)
   if (err)
     goto leave;
 
-  err = preorder_update_record (conn->dataitems);
+  err = preorder_update_record (&conn->dataitems);
 
  leave:
   if (err)
index 463acb1..4dc63cf 100644 (file)
@@ -208,7 +208,7 @@ main (int argc, char **argv)
   else if (cmd == aSepa)
     {
       if (argc != 2)
-        wrong_args ("--sepa REF AMOUNT");
+        wrong_args ("--sepa REF AMOUNT[/(RECUR|*)]");
       ascii_strupr (argv[0]);
       post_sepa (argv[0], argv[1]);
     }
@@ -325,8 +325,14 @@ send_request (const char *command, keyvalue_t indata, keyvalue_t *outdata)
 
   err = protocol_read_response (fp, outdata);
   if (err && (s=keyvalue_get (*outdata, "_errdesc")))
-    log_error ("Command failed: %s %s%s%s\n",
-               gpg_strerror (err), *s == '('?"":"(", s, *s == '('?"":")");
+    {
+      log_error ("Command failed: %s %s%s%s\n",
+                 gpg_strerror (err), *s == '('?"":"(", s, *s == '('?"":")");
+      if ((s=keyvalue_get (*outdata, "failure")))
+        log_info("                %s\n", s);
+      if ((s=keyvalue_get (*outdata, "failure-mesg")))
+        log_info("                %s\n", s);
+    }
   else if (err)
     log_error ("Error reading from payprocd: %s\n", gpg_strerror (err));
 
@@ -341,16 +347,42 @@ send_request (const char *command, keyvalue_t indata, keyvalue_t *outdata)
 
 
 static void
-post_sepa (const char *refstring, const char *amountstr)
+post_sepa (const char *refstring, const char *amountstr_arg)
 {
   gpg_error_t err;
   keyvalue_t input = NULL;
   keyvalue_t output = NULL;
   keyvalue_t kv;
+  char *amountstr;
+  int recur = 0;
+  char *p;
+
+  amountstr = xstrdup (amountstr_arg);
+
+  p = strchr (amountstr, '/');
+  if (p)
+    {
+      *p++ = 0;
+      if (!strcmp (p, "*"))
+        recur = -1;
+      else
+        recur = atoi (p);
+    }
 
   if (!*amountstr || !convert_amount (amountstr, 2))
     {
       log_error ("Syntax error in amount or value is not positive\n");
+      xfree (amountstr);
+      return;
+    }
+
+  switch (recur)
+    {
+    case -1: break;
+    case 0: case 1: case 4: case 12: break;
+    default:
+      log_error ("Syntax error in RECUR suffix - must be 0, 1, 4, 12 or *\n");
+      xfree (amountstr);
       return;
     }
 
@@ -360,6 +392,14 @@ post_sepa (const char *refstring, const char *amountstr)
     err = keyvalue_put (&input, "Amount", amountstr);
   if (!err)
     err = keyvalue_put (&input, "Currency", "EUR");
+  if (!err && recur)
+    {
+      if (recur == -1)
+        err = keyvalue_put (&input, "Recur", "*");
+      else
+        err = keyvalue_putf (&input, "Recur", "%d", recur);
+    }
+
   if (err)
     log_fatal ("keyvalue_put failed: %s\n", gpg_strerror (err));
 
@@ -371,6 +411,7 @@ post_sepa (const char *refstring, const char *amountstr)
 
   keyvalue_release (input);
   keyvalue_release (output);
+  xfree (amountstr);
 }
 
 
@@ -437,10 +478,13 @@ listpreorder (const char *refstring)
                 continue; /* Skip an empty last field.  */
               switch (i)
                 {
-                case 1: /* Created.   */
-                case 2: /* Last Paid - print only date.  */
+                case 1: /* Created - print only date.   */
                   es_printf (" %10.10s |", s );
                   break;
+                case 2: /* Last Paid - print time and date to ease
+                         * sorting.  */
+                  es_printf (" %19.19s |", s );
+                  break;
                 case 4:
                   t = strchr (s, '.');
                   len = t? (t-s) : strlen (s);
index 8192f4d..0acf1dd 100644 (file)
@@ -62,6 +62,7 @@
 #include "journal.h"
 #include "membuf.h"
 #include "dbutil.h"
+#include "currency.h"
 #include "preorder.h"
 
 
@@ -822,15 +823,16 @@ preorder_list_records (keyvalue_t *dictp, unsigned int *r_count)
 /* Take the Sepa-Ref from NEWDATA and update the corresponding row with
    the other data from NEWDATA.  On error return an error code.  */
 gpg_error_t
-preorder_update_record (keyvalue_t newdata)
+preorder_update_record (keyvalue_t *newdata)
 {
   gpg_error_t err;
   char separef[9];
   const char *s;
   char *p;
   keyvalue_t olddata = NULL;
+  int recur;
 
-  s = keyvalue_get (newdata, "Sepa-Ref");
+  s = keyvalue_get (*newdata, "Sepa-Ref");
   if (!s || strlen (s) >= sizeof separef)
     return gpg_error (GPG_ERR_INV_LENGTH);
   strcpy (separef, s);
@@ -846,10 +848,53 @@ preorder_update_record (keyvalue_t newdata)
   if (err)
     goto leave;
 
+  s = keyvalue_get_string (olddata, "Recur");
+  if (!valid_recur_p (s, &recur))
+    {
+      err = keyvalue_put (newdata, "failure-mesg",
+                          "Invalid value for 'Recur' in preorder record");
+      if (!err)
+        err = gpg_error (GPG_ERR_MISSING_VALUE);
+      goto leave;
+    }
+
+  /* Get the supplied Recur value and macth it with the preorder.  */
+  s = keyvalue_get_string (*newdata, "Recur");
+  if (!strcmp (s, "*") && !recur)
+    {
+      err = keyvalue_put (newdata, "failure-mesg",
+                          "Recurring donation but not claimed in preorder");
+      if (!err)
+        err = gpg_error (GPG_ERR_CONFLICT);
+      goto leave;
+    }
+  else if (!*s && recur)
+    {
+      err = keyvalue_put (newdata, "failure-mesg",
+                          "Single donation but preorder claims recurring");
+      if (!err)
+        err = gpg_error (GPG_ERR_CONFLICT);
+      goto leave;
+    }
+  else if (valid_recur_p (s, &recur))
+    {
+      /* RECUR updated - this overrides what we have in the preorder
+       * record.  */
+    }
+  else
+    {
+      err = keyvalue_put (newdata, "failure-mesg",
+                          "Invalid value for 'Recur' supplied");
+      if (!err)
+        err = gpg_error (GPG_ERR_MISSING_VALUE);
+      goto leave;
+    }
+
+
   /* Update OLDDATA with the actual amount so that we can put the
      correct amount into the log.  */
   err = keyvalue_put (&olddata, "Amount",
-                      keyvalue_get_string (newdata, "Amount"));
+                      keyvalue_get_string (*newdata, "Amount"));
   if (err)
     goto leave;
 
@@ -860,7 +905,7 @@ preorder_update_record (keyvalue_t newdata)
 
   /* FIXME: Unfortunately the journal function creates its own
      timestamp.  */
-  jrnl_store_charge_record (&olddata, PAYMENT_SERVICE_SEPA, 0);
+  jrnl_store_charge_record (&olddata, PAYMENT_SERVICE_SEPA, recur);
 
 
  leave:
index e720980..3f3c6a7 100644 (file)
@@ -21,7 +21,7 @@
 #define PREORDER_H
 
 gpg_error_t preorder_store_record (keyvalue_t *dictp);
-gpg_error_t preorder_update_record (keyvalue_t dict);
+gpg_error_t preorder_update_record (keyvalue_t *dict);
 gpg_error_t preorder_get_record (keyvalue_t *dictp);
 gpg_error_t preorder_list_records (keyvalue_t *dictp, unsigned int *r_count);