- Represents the status of a payroll.
- Available statuses:
- PENDING_APPROVAL
- APPROVE_FOR_PAYMENT
- REJECTED
- RECONCILED
- Represents the status of benefit consumption.
- Available statuses:
- ACCEPTED
- CREATED
- APPROVE_FOR_PAYMENT
- REJECTED
- DUPLICATE
- RECONCILED
- name: Name of the payment point.
- location: Foreign key to
Location. - ppm: Foreign key to
User.
- name: Name of the payroll.
- payment_plan: Foreign key to
PaymentPlan. - payment_cycle: Foreign key to
PaymentCycle. - payment_point: Foreign key to
PaymentPoint. - status: Status of the payroll (uses
PayrollStatuschoices). - payment_method: Method of payment.
- payroll: Foreign key to
Payroll. - bill: Foreign key to
Bill.
- payroll: Foreign key to
Payroll. - total_amount: Total amount as a string.
- bills_ids: JSON field for bill IDs.
- individual: Foreign key to
Individual. - photo: Text field for photo.
- code: Code for benefit consumption.
- date_due: Due date.
- receipt: Receipt number.
- amount: Amount (decimal).
- type: Type of benefit.
- status: Status of benefit consumption (uses
BenefitConsumptionStatuschoices).
- benefit: Foreign key to
BenefitConsumption. - bill: Foreign key to
Bill.
- payroll: Foreign key to
Payroll. - benefit: Foreign key to
BenefitConsumption.
- payroll: Foreign key to
Payroll. - status: Status of the reconciliation upload (uses
CsvReconciliationUpload.Statuschoices). - error: JSON field for errors.
- file_name: Name of the file.
- payroll: Foreign key to
Payroll. - mutation: Foreign key to
MutationLog.
This section details the configuration settings required for integrating with a digital payment gateway. The settings are defined in the application's configuration file (apps.py).
-
gateway_base_url: The base URL of the payment gateway's API.
- Example:
"http://41.175.18.170:8070/api/mobile/v1/"
- Example:
-
endpoint_payment: The endpoint for processing payments.
- Example:
"mock/payment"
- Example:
-
endpoint_reconciliation: The endpoint for reconciling payments.
- Example:
"mock/reconciliation"
- Example:
-
payment_gateway_api_key: The API key for authenticating with the payment gateway. It is retrieved from environment variables.
-
payment_gateway_basic_auth_username: The username for basic authentication with the payment gateway. It is retrieved from environment variables.
-
payment_gateway_basic_auth_password: The password for basic authentication with the payment gateway. It is retrieved from environment variables.
-
payment_gateway_timeout: The timeout setting for requests to the payment gateway, in seconds.
- Example:
5
- Example:
-
payment_gateway_auth_type: The type of authentication used by the payment gateway. It can be either 'token' or 'basic'.
- Example:
"basic"
- Example:
-
payment_gateway_class: The class that handles interactions with the payment gateway.
- Example:
"payroll.payment_gateway.MockedPaymentGatewayConnector"
- Example:
-
receipt_length: The length of the receipt generated for transactions.
- Example:
8
- Example:
{
"gateway_base_url": "http://41.175.18.170:8070/api/mobile/v1/",
"endpoint_payment": "mock/payment",
"endpoint_reconciliation": "mock/reconciliation",
"payment_gateway_api_key": os.getenv('PAYMENT_GATEWAY_API_KEY'),
"payment_gateway_basic_auth_username": os.getenv('PAYMENT_GATEWAY_BASIC_AUTH_USERNAME'),
"payment_gateway_basic_auth_password": os.getenv('PAYMENT_GATEWAY_BASIC_AUTH_PASSWORD'),
"payment_gateway_timeout": 5,
"payment_gateway_auth_type": "basic",
"payment_gateway_class": "payroll.payment_gateway.MockedPaymentGatewayConnector",
"receipt_length": 8
}To integrate the payment gateway, you need to define a class that extends the PaymentGatewayConnector and implements the necessary methods to handle payment and reconciliation requests.
from payroll.payment_gateway.payment_gateway_connector import PaymentGatewayConnector
class MockedPaymentGatewayConnector(PaymentGatewayConnector):
def send_payment(self, invoice_id, amount, **kwargs):
payload = {"invoiceId": str(invoice_id), "amount": str(amount)}
response = self.send_request(self.config.endpoint_payment, payload)
if response:
response_text = response.text
expected_message = f"{invoice_id} invoice of {amount} accepted to be paid"
if response_text == expected_message:
return True
return False
def reconcile(self, invoice_id, amount, **kwargs):
payload = {"invoiceId": str(invoice_id), "amount": str(amount)}
response = self.send_request(self.config.endpoint_reconciliation, payload)
if response:
return response.text == "true"
return FalseMake sure to set the following environment variables in your environment:
PAYMENT_GATEWAY_API_KEY: Your API key for the payment gateway.PAYMENT_GATEWAY_BASIC_AUTH_USERNAME: Your username for basic authentication.PAYMENT_GATEWAY_BASIC_AUTH_PASSWORD: Your password for basic authentication.
You can use either basic authentication or token authentication. Set the following variable accordingly:
The system supports configuring different payment gateway settings for specific payment points. This feature allows organizations to work with multiple payment providers.
Payment point-specific configurations are defined in the Django settings file under the PAYMENT_GATEWAYS dictionary. Each payment point has its own configuration dictionary that can override any of the global payment gateway settings:
PAYMENT_GATEWAYS = {
'payment_point_name_1': {
'gateway_base_url': 'https://api.payment-provider1.com/v1/',
'endpoint_payment': 'payments',
'endpoint_reconciliation': 'reconciliation',
'payment_gateway_auth_type': 'token',
'payment_gateway_api_key': 'payment_point_1_api_key',
'payment_gateway_timeout': 10,
'payment_gateway_class': 'payroll.payment_gateway.CustomPaymentGatewayConnector'
},
'payment_point_name_2': {
'gateway_base_url': 'https://api.payment-provider2.com/v2/',
'endpoint_payment': 'process-payment',
'endpoint_reconciliation': 'verify-payment',
'payment_gateway_auth_type': 'basic',
'payment_gateway_basic_auth_username': 'payment_point_2_username',
'payment_gateway_basic_auth_password': 'payment_point_2_password',
'payment_gateway_timeout': 15,
'payment_gateway_class': 'payroll.payment_gateway.AlternatePaymentGatewayConnector'
}
}Each payment point configuration can include the following parameters:
- gateway_base_url: The base URL for the payment gateway API specific to this payment point.
- endpoint_payment: The endpoint for processing payments.
- endpoint_reconciliation: The endpoint for reconciling payments.
- payment_gateway_auth_type: The authentication method ('token' or 'basic').
- payment_gateway_api_key: The API key for token authentication.
- payment_gateway_basic_auth_username: The username for basic authentication.
- payment_gateway_basic_auth_password: The password for basic authentication.
- payment_gateway_timeout: The timeout in seconds for API requests.
- payment_gateway_class: The Python class that implements the payment gateway connector.
If a parameter is not specified in the payment point configuration, the system will use the global value defined in PayrollConfig.
When processing a payroll, the system uses the payment_point name on the Payroll model to determine which configuration to use:
- If the
payment_pointvalue matches a key in thePAYMENT_GATEWAYSdictionary, the system uses that configuration. - If no matching configuration is found, or if
payment_pointis not set, the system uses the global configuration.
The payment_gateway_class parameter allows each payment point to use a different implementation for interacting with the payment gateway. This is particularly useful when different payment points need to integrate with completely different payment providers.
To create a custom connector:
- Create a class that extends
PaymentGatewayConnector - Implement the
send_paymentandreconcilemethods - Specify the fully-qualified class name in the payment point configuration
Example connector implementation:
from payroll.payment_gateway.payment_gateway_connector import PaymentGatewayConnector
class CustomPaymentGatewayConnector(PaymentGatewayConnector):
def send_payment(self, invoice_id, amount, **kwargs):
payload = {
"reference": str(invoice_id),
"amount": float(amount),
"currency": "USD"
}
response = self.send_request(self.config.endpoint_payment, payload)
if response and response.status_code == 200:
data = response.json()
return data.get('status') == 'success'
return False
def reconcile(self, invoice_id, amount, **kwargs):
payload = {
"reference": str(invoice_id),
"amount": float(amount)
}
response = self.send_request(self.config.endpoint_reconciliation, payload)
if response and response.status_code == 200:
data = response.json()
return {
"transaction_id": data.get('transaction_id'),
"status": data.get('status'),
"timestamp": data.get('timestamp')
}
return FalsePayment gateway credentials should be stored securely:
- Do not hardcode API keys or passwords in your settings file
- Use environment variables to store sensitive information
- Consider using a secrets management solution for production environments
Example secure configuration:
PAYMENT_GATEWAYS = {
'secure_payment_point': {
'gateway_base_url': os.getenv('PAYMENT_POINT_URL'),
'payment_gateway_auth_type': 'token',
'payment_gateway_api_key': os.getenv('PAYMENT_POINT_API_KEY')
}
}When the payment_method of a Payroll is set to StrategyOnlinePayment, the configuration described below is required for the payment and reconciliation process.
- Populate/Generate Payroll: Ensure the payroll has
payment_method='StrategyOnlinePayment'. - Accept or Reject Payroll: Use the maker-checker logic to either accept or reject the payroll.
- Accepted Payroll:
- Navigate to
Legal and Finance (Payments) -> Accepted Payrolls. - Click the
Make Paymentbutton. This triggers the payment flow defined in the configuration.
- Navigate to
- Invoice Submission:
- If all invoices are sent successfully, go to the view reconciliation summary.
- Invoices that were accepted will have their status changed from
AcceptedtoApproved for Payment.
- Close Payroll:
- In the same view, click the
Accept and Close Payrollbutton.
- In the same view, click the
- Task View:
- Go to payroll details and click the
Tasksview. - At the top of the searcher, you should see a
Reconciliationtask.
- Go to payroll details and click the
- Accept or Reject Task:
- Accept or reject the reconciliation task.
- If accepted, the reconciliation flow is triggered. Payments are reconciled if the feedback from the payment gateway is successful without any issues. The status for the benefit will be
Reconciled. The payroll will now be visible inPayrolls -> Reconciled Payrolls.
- Error Handling:
- Even if the payroll is reconciled, some benefits might not be paid due to errors.
- The status will remain
Approved for Payment. - Errors can be viewed by clicking the
Errorbutton. - Unpaid Payroll's invoices can be recreated during re-creation of payroll in reconciled payroll
- Recreate Unpaid Invoices:
- Unpaid payroll invoices can be recreated during the re-creation of payroll in the reconciled payroll section.
- The unpaid invoices will be included in the new payroll.
- Use the
Create Payroll from Unpaid Invoicesbutton available when you go toLegal and Finance -> Reconciled Payrolls -> View Reconciled Payroll -> Create Payment from Failed Invoice.
When the payment_method of a Payroll is set to StrategyOfflinePayment, the configuration described below is required for the offline payment and reconciliation process.
- Create Payroll:
- Navigate to
Legal and Finance (Payments) -> Payrolls. - Click the
+(add payroll) button to create a new payroll.
- Navigate to
- Choose Payment Method:
- Select
StrategyOfflinePaymentas the payment method.
- Select
- Accept or Reject Payroll:
- Use the maker-checker logic to either accept or reject the payroll.
- Go to the
Taskstab on the payroll details page to perform this action.
- Accepted Payroll:
- If the payroll task is accepted, a new button
Upload Payment Databecomes available. - Click
Downloadto view theinvoicesattached to the payroll in CSV format.
- If the payroll task is accepted, a new button
- Prepare Reconciliation File:
- To reconcile a benefit/invoice, fill in the
Paidcolumn withYesand generate aReceiptnumber. - If the payment is not made, do not add a receipt number and set the
Paidcolumn toNo. Alternatively, remove the unpaid record from the file entirely.
- To reconcile a benefit/invoice, fill in the
- Upload Payment Data:
- Once the file is prepared, upload it by clicking
Upload Payment Data. - After uploading, you should see the
paymentsdata reconciled based on thePaidstatus and the presence of a receipt number.
- Once the file is prepared, upload it by clicking
- Reconcile Payroll:
- Click
View Reconciliation SummaryunderLegal and Finance (Payments) -> Reconciled Payrolls. - If you click
Approve and Close, to confirm the reconciliation, go toTaskseither in theAll Tasksview or on thePayrollpage in theTaskstab.
- Click
- Recreate Unpaid Invoices:
- Unpaid payroll invoices can be recreated during the re-creation of payroll in the reconciled payroll section.
- The unpaid invoices will be included in the new payroll.
- Use the
Create Payroll from Unpaid Invoicesbutton available when you go toLegal and Finance -> Reconciled Payrolls -> View Reconciled Payroll -> Create Payment from Failed Invoice.