POS + General Ledger + Inventory + Payroll — All Included on Every Plan | Free Updates Forever

How Automatic Invoice Generation Works

How Automatic Invoice Generation Works

AccuArk automatically generates invoices from recurring templates every time the application starts. This guide explains the complete auto-generation process, how frequency calculations advance the schedule, what happens when templates reach their end date, how errors are handled, and how manual generation compares to the automatic process.

When Auto-Generation Runs

The auto-generation process runs during application startup in application startup. After the database connection is established and the user is logged in, AccuArk calls RecurringAccuArk.GenerateDueInvoicesAsync(). This method queries the recurring_invoice_templates table for all templates that meet three conditions:

  1. The template is active (is_active = 1).
  2. The next_generation_date is on or before today's date.
  3. The end_date is either null or is on or after today's date.

If any templates match these criteria, AccuArk processes each one in sequence. If the application is not started on a given day (for example, over a weekend), the due invoices accumulate and are all generated the next time AccuArk is opened.

The Generation Process Step by Step

For each due template, RecurringAccuArk.GenerateFromTemplateAsync performs the following steps:

Step 1: Parse the Items JSON

The template's items_json field is parsed into a list of RecurringItem objects. Each item contains an inventory item ID, item name, quantity, and unit price. If the JSON is empty or contains no valid items, generation is skipped for this template and an error result is returned with the message "Template has no items."

Step 2: Create the Invoice

A new invoice is created with the following values copied from the template:

  • LocationId — the template's location.
  • ClientId — the template's customer.
  • InvoiceType — the invoice type stored on the template.
  • InvoiceShipping — the template's shipping amount.
  • InvoiceDiscount — the template's discount amount.
  • InvoiceNotes — the template's notes text.
  • Terms — the template's terms text.
  • InvoiceDateEntered — set to the current date and time.
  • InvoiceDueDate — set to 30 days from the current date (default Net 30 terms).
  • InvoiceStatusId — set to 1 (Active).

Step 3: Calculate Totals

The items subtotal is calculated by summing (quantity multiplied by price) for each line item. The invoice total is then computed as: items subtotal plus shipping amount minus discount amount. The invoice balance is set equal to the total since no payments have been applied yet.

Step 4: Save the Invoice

The invoice is saved to the database to the database. If saving fails, the generation result is marked as failed with the error message "Failed to create invoice."

Step 5: Insert Invoice Line Items

Each item from the parsed JSON is inserted into the invoice_items table with the new invoice's ID. The items include the inventory_id, item_name, item_quantity, item_price, item_subtotal, and item_total. Items are inserted in order with an incrementing item_order value starting at 1.

Step 6: Record the Generation

The template's RecordGenerationAsync method is called, which performs three updates in a single SQL statement:

  • Sets last_generated_invoice_id to the new invoice's ID.
  • Sets last_generated_at to the current timestamp.
  • Increments total_generated by 1.
  • Advances next_generation_date to the next occurrence based on the frequency.

Step 7: Create a Log Entry

A log entry is created with the template ID, the generated invoice ID, the generation timestamp, and the initial auto-email status. This log entry is saved to the recurring_invoice_log table.

Step 8: Send Auto-Email (If Configured)

If the template has AutoEmail enabled, the service attempts to send the invoice by email:

  1. The location's email settings are loaded using DbEmailSettings.GetEffectiveSettingsAsync.
  2. If email is configured and enabled, the customer's email address is retrieved from the customer record.
  3. If the customer has a valid email address, the subject and body are prepared with placeholder substitution — {InvoiceId}, {CustomerName}, and {Total} are replaced with actual values.
  4. The email is sent via EmailService.SendEmailAsync.
  5. The log entry's auto_emailed and email_status fields are updated to reflect the result.

If any step in the email process fails, the invoice is still considered successfully generated. The email failure is recorded in the log entry with a status like "no_email_on_file," "email_not_configured," or the error message. The generation result itself is marked as successful because the invoice was created — the email is a secondary action.

Frequency Calculations

After each generation, the Next Generation Date is advanced based on the template's frequency setting. The CalculateNextDate using the following logic performs the following calculations from the current Next Generation Date:

  • Weekly — adds 7 days.
  • Bi-Weekly — adds 14 days.
  • Monthly — adds 1 calendar month using AddMonths(1). This correctly handles months with different lengths.
  • Quarterly — adds 3 calendar months.
  • Semi-Annual — adds 6 calendar months.
  • Annual — adds 1 year using AddYears(1). This correctly handles leap years.
  • Custom — adds the configured CustomIntervalDays value. If CustomIntervalDays is null, it defaults to 30 days.

The calculation always advances from the current Next Generation Date, not from today's date. This ensures the schedule stays consistent even if the application is not opened on the exact due date.

End Date Behavior

If a template has an end date set, the GetDueAsync query includes a condition that filters out templates where the end_date has passed. This means that once today's date exceeds the template's end date, the template will no longer appear in the list of due templates and no further invoices will be generated.

The template remains active in the database — it is not automatically deactivated when the end date passes. However, it is effectively dormant because the query excludes it. If you extend the end date to a future date, the template will resume generating invoices on the next startup.

Error Handling

The auto-generation process is designed to be fault-tolerant. Each template is processed independently inside a try-catch block. If one template fails to generate an invoice (due to a database error, invalid data, or any other exception), the error is logged via ErrorLog.LogErrorAsync and the service continues processing the remaining templates.

This means a single broken template does not block the generation of invoices from other templates. The failed template's GenerationResult is included in the results list with Success = false and the error message preserved.

The outer GenerateDueInvoicesAsync method also has its own try-catch wrapper. If the initial query for due templates fails, the error is logged and an empty results list is returned. The application startup continues normally — recurring invoice generation failures do not prevent users from using AccuArk.

Manual Generation

The Generate Now button on the Recurring Invoices screen triggers the same GenerateFromTemplateAsync method used by the automatic process. The only difference is that manual generation does not check whether the Next Generation Date has been reached — it generates an invoice immediately regardless of the schedule.

After manual generation, the Next Generation Date is still advanced to the next occurrence, which means the next automatic generation will happen on schedule relative to the manual generation date.

What to Read Next

  • Creating a Recurring Invoice Template — Set up templates that feed into the auto-generation process.
  • Managing Recurring Invoice Templates — Monitor and control your templates from the management screen.
  • Viewing Recurring Invoice History — Review the log of generated invoices and troubleshoot failures.
Was this article helpful?
Back to Complex Invoicing Contact Support
Please note: This article is intended as a general guide. AccuArk© is continuously improved through regular software updates, so some screens, labels, or features described here may appear slightly different in your version. If something doesn't match or you need further assistance, please don't hesitate to contact our support team.
Still need help?

Our support team is ready to assist you.

Submit a Ticket