Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
118 lines
3.8 KiB
JavaScript
118 lines
3.8 KiB
JavaScript
/**
|
|
* Migration: system task definitions + shared form for accounting sync
|
|
* exceptions (drift, unmapped payments, export errors, unlinked customers,
|
|
* expired connections). Supersedes the never-wired qbo_mapping_error type,
|
|
* which is left in place for any existing tasks.
|
|
*/
|
|
|
|
const FORM_NAME = 'accounting-sync-exception-form';
|
|
|
|
const TASK_TYPES = [
|
|
{
|
|
task_type: 'accounting_sync_drift',
|
|
name: 'Resolve accounting sync drift',
|
|
description: 'An exported document was changed, voided, or deleted in the accounting system.'
|
|
},
|
|
{
|
|
task_type: 'accounting_sync_unmapped_payment',
|
|
name: 'Resolve unmapped accounting payment',
|
|
description: 'A payment in the accounting system references an invoice Alga does not know.'
|
|
},
|
|
{
|
|
task_type: 'accounting_sync_export_error',
|
|
name: 'Resolve accounting export error',
|
|
description: 'A scheduled accounting export failed validation or delivery.'
|
|
},
|
|
{
|
|
task_type: 'accounting_sync_customer_unlinked',
|
|
name: 'Re-link accounting customer',
|
|
description: 'A linked accounting customer was deleted, merged, or made inactive.'
|
|
},
|
|
{
|
|
task_type: 'accounting_connection_expired',
|
|
name: 'Reconnect accounting integration',
|
|
description: 'The accounting connection failed authentication and needs to be reconnected.'
|
|
}
|
|
];
|
|
|
|
const FORM = {
|
|
json_schema: {
|
|
type: 'object',
|
|
properties: {
|
|
message: { type: 'string', title: 'What happened', readOnly: true },
|
|
details: { type: 'string', title: 'Details', readOnly: true },
|
|
settingsLink: {
|
|
type: 'string',
|
|
title: 'Accounting Integration Settings',
|
|
format: 'uri',
|
|
description: 'Open the accounting integration settings'
|
|
}
|
|
},
|
|
required: ['message']
|
|
},
|
|
ui_schema: {
|
|
message: { 'ui:widget': 'AlertWidget', 'ui:options': { alertType: 'warning' } },
|
|
details: { 'ui:widget': 'textarea', 'ui:options': { rows: 6 } },
|
|
settingsLink: {
|
|
'ui:widget': 'ButtonLinkWidget',
|
|
'ui:options': { buttonText: 'Open Integration Settings', target: '_blank' }
|
|
},
|
|
'ui:order': ['message', 'details', 'settingsLink']
|
|
},
|
|
default_values: {
|
|
message: '${contextData.message}',
|
|
details: '${contextData.details}',
|
|
settingsLink: '/msp/settings?tab=integrations&category=accounting'
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {import('knex').Knex} knex
|
|
*/
|
|
exports.up = async function up(knex) {
|
|
await knex.transaction(async (trx) => {
|
|
const existingForm = await trx('system_workflow_form_definitions').where({ name: FORM_NAME }).first();
|
|
if (!existingForm) {
|
|
await trx('system_workflow_form_definitions').insert({
|
|
name: FORM_NAME,
|
|
description: 'Shared form for accounting sync exceptions.',
|
|
version: '1.0',
|
|
status: 'ACTIVE',
|
|
json_schema: JSON.stringify(FORM.json_schema),
|
|
ui_schema: JSON.stringify(FORM.ui_schema),
|
|
default_values: JSON.stringify(FORM.default_values),
|
|
created_by: null,
|
|
created_at: new Date(),
|
|
updated_at: new Date()
|
|
});
|
|
}
|
|
|
|
for (const task of TASK_TYPES) {
|
|
const existing = await trx('system_workflow_task_definitions').where({ task_type: task.task_type }).first();
|
|
if (!existing) {
|
|
await trx('system_workflow_task_definitions').insert({
|
|
...task,
|
|
form_id: FORM_NAME,
|
|
form_type: 'system',
|
|
default_priority: 'medium',
|
|
created_by: null,
|
|
created_at: new Date(),
|
|
updated_at: new Date()
|
|
});
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* @param {import('knex').Knex} knex
|
|
*/
|
|
exports.down = async function down(knex) {
|
|
await knex.transaction(async (trx) => {
|
|
await trx('system_workflow_task_definitions')
|
|
.whereIn('task_type', TASK_TYPES.map((task) => task.task_type))
|
|
.del();
|
|
await trx('system_workflow_form_definitions').where({ name: FORM_NAME }).del();
|
|
});
|
|
};
|