P4 Software / cifraHQ

Administrator Guide

Administrator Guide

This guide is for the tenant administrator responsible for enabling and configuring the ITBMS withholding agent module before AP clerks start posting payments.


When you need this

Your tenant has been designated by the DGI as an ITBMS withholding agent under Resolución 201-8055 (or a successor resolution) and you need to enable CifraHQ's automated retention pipeline.

Foreign or non-Panama tenants do not need any configuration. Leave Designated ITBMS Withholding Agent off and the entire module stays inert.


One-time Setup

1. Open the configuration page

Navigate to Accounting → ITBMS Withholdings (Settings). The first time you open the page, CifraHQ creates a default config row in your tenant database with sensible defaults (50% rate, OnPayment trigger, RT- certificate prefix).

2. Designate the agent

Fill in the Agent Designation section:

Field What to enter
Designated ITBMS Withholding Agent Toggle on
Designation Reference The resolution that named you (e.g., "Resolución 201-8055 / 2026-2027")
Effective From The start date of your designation period
Effective To The end date of your designation period (typically biennial)

The system honors the effective window: payments outside the window will not generate retentions, even if the agent flag is on.

3. Confirm retention behavior

Field DGI default Notes
Retention Rate 50% The DGI-mandated rate. Override only if a future regulation changes it.
Trigger Event On payment (DGI canonical) When the retention is issued. The alternative ("On invoice post") is a Phase 2 option.
Require CPA Approval to Close Off (toggle on if your annual revenue > USD 11,000) When on, the monthly period close routes to a CPA user for approval.

4. Set certificate numbering

Field Notes
Certificate Prefix Default RT-. Used as {prefix}{8-digit-zero-padded-sequence} (e.g., RT-00000001).
Next Certificate Number Read-only. The engine increments this atomically under optimistic concurrency.
Automatically Email Certificate to Supplier Toggle on if you want every issued certificate emailed when generated.

5. Pick the GL accounts

The retention engine emits two-line Journal Entries against these accounts:

Account Used when
ITBMS Withheld Payable You are the agent: CR this liability account when a retention is issued; DR when voided. Typically a 2-04-xx code in a Panama CoA.
ITBMS Withheld Receivable You are a supplier registering a certificate received from your customer: DR this asset account when the certificate is matched. Typically a 1-04-xx code.

If either account is unset, retentions still persist in the subledger but the corresponding Journal Entry is not posted. The Form 4331 monthly validation step will surface the gap.

New tenants get these accounts pre-created. As of CifraHQ 2.3.x, every new tenant's default Chart of Accounts now includes:

  • 116000 - ITBMS Withheld Receivable (asset, ITBMS Retenido por Cobrar in Spanish)
  • 231500 - ITBMS Withheld Payable (liability, ITBMS Retenido por Pagar in Spanish)

A backfill migration also runs against existing tenants on the first upgrade after 2.3.0: it inserts the two accounts if they're missing, and auto-binds them to the singleton TenantWithholdingConfig row when the FKs are still null. So on most tenants you'll find the two accounts already picked when you open Accounting → ITBMS Withholdings (Settings) for the first time. Verify they match your CoA conventions before going live - you can change to any other liability/asset account in the same category.


Configure the supplier (vendor) master

Once the agent flag is enabled, the Vendor detail page shows a new ITBMS Withholding section. For each vendor:

Field When to change it
Tax Domicile Default Panama. Set to United States, Mexico, Canada, or Other for foreign Vendors.
Subject to ITBMS withholding Auto-managed: turns off when Tax Domicile is anything other than Panama. Override for special cases.
ITBMS Retention Rate Override Leave blank to use the tenant default (50%). Set a value only for Vendors under a special regime that mandates a different rate.
Exemption Reason None / Free Trade Zone / Special Regime / Small Taxpayer / Foreign / Other
Exemption Document Reference The DGI resolution number that grants the exemption
Exemption Valid Until The expiration of the exemption - the system warns when older than 365 days

The fastest way to skip a vendor entirely is to set Tax Domicile correctly. A US (Miami) vendor with no ITBMS on the invoice would yield zero retention anyway, but the domicile setting makes the intent explicit.


Test that the pipeline works

After Setup, run this smoke test against a Panama vendor:

  1. Pick or create a vendor with Tax Domicile = Panama and Subject to ITBMS withholding = on, with an email address
  2. Create a Vendor Bill with one line: USD 1,000 subtotal + USD 70 ITBMS (10%)
  3. Post the bill
  4. Create a Bill Payment for the bill, full amount (USD 1,070), post it
  5. Within 30 seconds, check Accounting → General Ledger for a Journal Entry referenced "ITBMSRetention": DR your AP account USD 35, CR ITBMS Withheld Payable USD 35
  6. Check the vendor's email inbox for the certificate PDF (if auto-email is on and ACS is configured)

If steps 5–6 don't happen, see the troubleshooting section of the Withholding Agent Guide.


Vendor RUC verification

The Vendor detail page has a Verify Tax ID button next to the RUC field (mirrors the Customer page that has had this for years). Click it after you enter the supplier's RUC and CifraHQ will:

  1. Call the public DGI registry lookup for that RUC
  2. Auto-populate Legal Name with the name on file at DGI
  3. Auto-populate Tax Domicile (typically Panama for a Panamanian RUC, Other for foreign Vendors with a Cédula extranjera style ID)
  4. Flag the vendor's Withholding section if the DGI registry indicates a special regime (free trade zone, small taxpayer, etc.)

Why this matters for the withholding flow:

  • A Panamanian RUC that isn't on the DGI registry is a red flag - you should refuse to onboard the vendor until you've reconciled the discrepancy. The verify button surfaces this immediately rather than after you've already issued a certificate that DGI later rejects.
  • A correct Legal Name is what prints on the retention certificate PDF in the PROVEEDOR RETENIDO row. DGI cross-references this against your Form 4331 submission and the supplier's own Form 430 - mismatched names trigger inspector queries.
  • Tax Domicile auto-fill removes the manual step that was causing rural / non-Panama Vendors to be silently included in the retention pipeline.

The same button is available from a vendor's Code lookup (/api/Vendor/VerifyTaxIdByCode?code=...), useful when you only have the vendor code from an imported CSV.


Orphan recovery (when a retention exists without a certificate)

In rare cases - typically when a deploy lands mid-payment-posting or an external dependency (GL posting period missing, configured account suddenly invalid) trips the engine - you can end up with an ITBMSRetention row in Issued state that has no matching RetentionCertificate row. The Form 4331 close-validation step will block the period close until this is fixed.

CifraHQ ships with a one-shot recovery endpoint:

POST /api/RetentionCertificate/ReissueByPayment?paymentId={billPaymentId}

What it does:

  1. Re-runs the calculation against the existing posted Bill Payment
  2. Finds the orphan retention (by (SourceDocId, PaymentId) tuple)
  3. Allocates a fresh certificate number from the tenant config sequence
  4. Creates the missing RetentionCertificate row
  5. If no Journal Entry exists for the retention, re-emits it
  6. Enqueues the CertificateDeliveryJob so the PDF gets generated, uploaded, and emailed

The endpoint is idempotent: calling it on a payment that already has a healthy certificate just Returns the existing certificate and does nothing else.

When to use it:

Situation Action
Form 4331 validation says "uncertified retention" Run ReissueByPayment for each affected payment
Bill Payment shows posted but no Withholding Certificate panel, and you've waited 60+ seconds Run ReissueByPayment
Mass recovery after an outage Query ITBMSRetentions r LEFT JOIN RetentionCertificates c ON c.RetentionId = r.Id WHERE c.Id IS NULL, then call ReissueByPayment for each r.PaymentId

The job state appears in /hangfire - successful runs leave a clear Audit Trail.


Run the template seeder

The certificate template is built programmatically in C# at seed time using the Stimulsoft .NET API and saved in XML format. This eliminates the entire class of "JSON template loaded fine in the designer but crashes the server-side render" problems that plagued earlier hand-rolled templates.

Once per tenant (and again after a CifraHQ version bump that ships an updated template):

POST /api/WithholdingTemplateSeeder/Seed

The endpoint Returns a JSON list of created/updated/skipped templates:

{
  "Created": [],
  "Updated": ["RetentionCertificate"],
  "Skipped": []
}
  • Created - first-time seed; no PrintReports row existed for that name
  • Updated - the row existed and is stock (IsCustom = false), so it was overwritten with the latest binary
  • Skipped - the row exists but is marked IsCustom = true (someone customized the template in the Stimulsoft designer); the customization is left intact

Safe to re-run any time - the new programmatic build always emits the same canonical XML bytes, so a re-seed never introduces a load-time crash on the .NET render path.

Customizing the template

You can edit the seeded template in the Stimulsoft web designer (link on the PrintReports admin page). The designer saves your edits in JSON format, which is what the JS designer uses - and which the JS designer also loads back cleanly. The PDF render path stays robust because the data binding is the same in both formats; only the wire encoding changes.

If you ever upload a JSON template that the server-side renderer rejects with InvalidCastException - Unable to cast object of type 'JValue' to type 'JObject' (a known Stimulsoft .NET 2025.x quirk with hand-rolled JSON), re-run the seeder - it will replace the broken JSON with the canonical XML and your customizations will need to be reapplied through the designer.


Disabling the agent flag

You can only disable the Designated ITBMS Withholding Agent flag when there are no open (Issued or Draft) retentions in the current period. If retentions exist, close the current Form 4331 first.

This guard prevents orphaned certificates and protects the GL.


Permissions

  • ITBMS Withholdings (Settings) config page - reached from the Accounting menu (route /settings/taxes/itbms-withholdings) - administrator role
  • Form 4331 generation and submission - tax accountant role
  • Vendor withholding fields - anyone with vendor master edit rights
  • Certificate void - administrator or tax accountant

Was this page helpful?