App-GnuCash-MembershipUtils

 view release on metacpan or  search on metacpan

bin/gc-members-generate-invoices  view on Meta::CPAN

## Set STDOUT to autoflush
$| = 1;    ## no critic (RequireLocalizedPunctuationVars)

## Parse the command line
process_commandline();

my $dt_tz = DateTime::TimeZone->new( name => 'local' );
my $inv_open_dt;
if ($gOptions{open}) {
    $inv_open_dt = DateTime::Format::DateParse->parse_datetime($gOptions{open});
} else {
    # Default is first of the current month
    $inv_open_dt = DateTime->today( time_zone => $dt_tz, )->set_day(1);
}

my $inv_due_dt;
if ($gOptions{due}) {
    $inv_due_dt = DateTime::Format::DateParse->parse_datetime($gOptions{due});
} else {
    # Default is last of current month.
    # This is done by getting the 1st day of next month and subtrating 1 day
    $inv_due_dt = DateTime->today( time_zone => $dt_tz, )->set_day(1)->add(months => 1)->subtract(days => 1);
}

if ($inv_open_dt > $inv_due_dt) {
  printf STDERR "ERROR: The opening date cannot be after the due date!\n";
  exit(1);
}

my ($error, $config) = get_config($gOptions{config}, $gOptions{debug});

if ($error) {
  printf STDERR "Error getting config: %s\n", $error;
  exit(1);
}

$gOptions{format} //= $config->{GnuCash}{format};
unless ($DATE_FORMATS{lc($gOptions{format})}) {
    printf STDERR "Invalid date format option '%s'. Must be one of '%s'\n",
        $gOptions{format},
        join("', '", keys(%DATE_FORMATS));
    exit(1);
}

$gOptions{memo} //= $config->{GnuCash}{memo};

$gOptions{note} //= $inv_open_dt->strftime("%B membership dues");

unless ($gOptions{outfile}) {
    $gOptions{outfile} = DateTime->today( time_zone => $dt_tz, )->strftime("%Y-%m-%d_gnucash_customer_invoices.csv");
}

my $schema;
($error, $schema) = open_gnucash(get_gnucash_filename($gOptions{file}, $config));
if ($error) {
  printf STDERR "Error opening GnuCash file: %s\n", $error;
  exit(1);
}

my $warning;
($error, $warning) = validate_accounts_in_config({
  schema => $schema,
  config => $config,
});
say STDERR $warning if ($warning);
if ($error) {
  say STDERR $error;
  exit(1);
}

my @members = get_all_members({
  active_only => 1,
  schema      => $schema,
  config      => $config,
  debug       => $gOptions{debug},
});

my $last_inv_id = $schema->resultset('Invoice')->last_invoice_id;
my $next_inv_id = $last_inv_id + 1;
printf(
    join(
        "\n",
        "Output File:   '%s'",
        "Opening Date:  %s",
        "Due Date:      %s",
        "Item Memo:     '%s'",
        "Invoice Memo:  '%s'",
        "First Invoice: '%06d'",
        "",
    ),
    $gOptions{outfile},
    format_date($inv_open_dt),
    format_date($inv_due_dt),
    $gOptions{memo},
    $gOptions{note},
    $next_inv_id,
);

my $csv = Text::CSV->new ({
  # Cannot quote spaces, or GnuCash won't find your accounts
  quote_space => 0,
  sep_char    => ';',
  binary      => 1,
  auto_diag   => 1,
});

my %inv_template = (
  date_opened    => format_date($inv_open_dt),
  date           => format_date($inv_open_dt),
  date_posted    => format_date($inv_open_dt),
  due_date       => format_date($inv_due_dt),
  quantity       => 1,
  account_posted => $config->{GnuCash}{account},
  memo_posted    => $gOptions{note},
  accu_splits    => "Y",
);

## no critic (InputOutput::RequireBriefOpen)
if (open my $fh, ">:encoding(utf8)", $gOptions{outfile}) {
  for my $member (@members) {
      my %inv = (



( run in 1.275 second using v1.01-cache-2.11-cpan-ff9377addf4 )