321 lines
12 KiB
JavaScript
321 lines
12 KiB
JavaScript
'use strict';
|
|
/*
|
|
Centralized constants for the application
|
|
*/
|
|
const Units = Object.freeze({ OZ: 0, GAL: 1, LB: 2, LIT: 3, KG: 4, ACRE: 5, HA: 6, HOUR: 7, GR: 8, CC: 9, PT: 10 });
|
|
|
|
// Rate Units constants for application rates
|
|
const RateUnits = Object.freeze({
|
|
OZ_PER_ACRE: 0, // oz/ac - ounces per acre (fluid)
|
|
GAL_PER_ACRE: 1, // gal/ac - gallons per acre
|
|
LBS_PER_ACRE: 2, // lbs/ac - pounds per acre
|
|
LIT_PER_HA: 3, // lit/ha - liters per hectare
|
|
KG_PER_HA: 4 // kg/ha - kilograms per hectare
|
|
});
|
|
|
|
// HTTP Status Codes (frozen for consistency across application)
|
|
const HttpStatus = Object.freeze({
|
|
OK: 200,
|
|
CREATED: 201,
|
|
NO_CONTENT: 204,
|
|
BAD_REQUEST: 400,
|
|
UNAUTHORIZED: 401,
|
|
PAYMENT_REQUIRED: 402,
|
|
FORBIDDEN: 403,
|
|
NOT_FOUND: 404,
|
|
CONFLICT: 409,
|
|
GONE: 410,
|
|
INTERNAL_SERVER_ERROR: 500,
|
|
SERVICE_UNAVAILABLE: 503
|
|
});
|
|
|
|
const ExportType = Object.freeze({ CSV: "csv", IIF: "iif" });
|
|
|
|
const APTypes = Object.freeze(
|
|
{
|
|
ACTIVE: 1,
|
|
CARRIER: 9
|
|
});
|
|
|
|
const RecTypes = Object.freeze({
|
|
UNKNOWN: 0,
|
|
AGN_BIN_LQD: 1,
|
|
AGN_BIN_DRY: 2,
|
|
AGN_AMS: 3,
|
|
AGN_SHP: 4,
|
|
AGN_SHP_DRY: 5,
|
|
SATLOG: 10
|
|
});
|
|
|
|
const UserTypes = Object.freeze({ ADMIN: "0", APP: "1", APP_ADM: "2", CLIENT: "3", OFFICER: "4", PILOT: "5", INSPECTOR: "6", DEVICE: "9", PARTNER: "20", PARTNER_SYSTEM_USER: "21" });
|
|
|
|
const AppStatus = Object.freeze({
|
|
ERROR: 0,
|
|
CREATED: 1,
|
|
IN_PROGRESS: 2,
|
|
WAS_CANCELLED: -1,
|
|
DONE: 3
|
|
});
|
|
|
|
const AppProStatus = Object.freeze({
|
|
ERROR: 0, // not fully processed (disrupted while reading or processing files)
|
|
WITH_DATA: 1,
|
|
NO_DATA: 2
|
|
// 10 + STATUS: If items were updated
|
|
});
|
|
|
|
const AssignStatus = Object.freeze({
|
|
NEW: 0,
|
|
DOWNLOADED: 1,
|
|
UPLOADED: 2 // Status for jobs uploaded to partner systems
|
|
});
|
|
|
|
const Fields = Object.freeze({ MARKED_DELETE: 'markedDelete' });
|
|
|
|
const DEFAULT_LANG = 'en';
|
|
const DEL_APP_IDS = "DEL_APP_IDS"; // The key name of deleted appIds cached list using REDIS
|
|
const LIMIT_FILE_SIZE_ERR = "LIMIT_FILE_SIZE"; // MulterError code for file too large
|
|
|
|
const DEFAULT_TRIAL_DAYS = [15, 30, 60, 90, 120, 180, 270, 365];
|
|
|
|
// Promotion mode (global promo application behavior)
|
|
const PromoModes = Object.freeze({
|
|
ENABLED: 'enabled', // Promotions enabled (targeting controlled by PromoEligibility)
|
|
DISABLED: 'disabled' // Kill switch: disable all automatic promos
|
|
});
|
|
|
|
// Stripe coupon duration types
|
|
const CouponDuration = Object.freeze({
|
|
FOREVER: 'forever', // Coupon applies indefinitely
|
|
REPEATING: 'repeating', // Coupon applies for N months
|
|
ONCE: 'once' // Coupon applies once (not supported in V2)
|
|
});
|
|
|
|
// Stripe error types
|
|
const StripeErrorTypes = Object.freeze({
|
|
CARD_ERROR: 'StripeCardError', // Card-related errors (declined, insufficient funds, etc.)
|
|
INVALID_REQUEST: 'StripeInvalidRequestError', // Invalid parameters or request
|
|
API_ERROR: 'StripeAPIError', // Stripe API errors
|
|
CONNECTION_ERROR: 'StripeConnectionError', // Network connection errors
|
|
AUTHENTICATION_ERROR: 'StripeAuthenticationError', // Authentication errors
|
|
RATE_LIMIT_ERROR: 'StripeRateLimitError' // Rate limiting errors
|
|
});
|
|
|
|
// Standard action labels for API mutation responses
|
|
const APIActions = Object.freeze({
|
|
DISABLED: 'disabled',
|
|
DELETED: 'deleted',
|
|
UPDATED: 'updated'
|
|
});
|
|
|
|
const TrialTypes = Object.freeze({
|
|
NONE: null,
|
|
DAYS: 'days',
|
|
BY_DATE: 'byDate'
|
|
});
|
|
|
|
// Error constant codes mapped to tags
|
|
const Errors = Object.freeze({
|
|
NOT_FOUND: 'not_found',
|
|
NO_ACCESS: 'not_authorized', ACC_INACTIVE: 'acc_inactive', INVALID_ACCOUNT: 'invalid_account', WRONG_CREDENTIAL: 'wrong_credential',
|
|
INVALID_TOKEN: 'invalid_token', ACTIVE_ACCOUNT: 'active_account', INVALID_EMAIL: 'invalid_email', EMAIL_ERROR: 'email_error',
|
|
PARENT_NOT_EXIST: 'parent_not_exist', USER_NOT_FOUND: 'user_not_found', USER_EXIST: 'user_exist', TOKEN_EXPIRED: 'token_expired', PILOT_NOT_EXIST: 'pilot_not_exist',
|
|
JOB_NOT_FOUND: 'job_not_found', NO_SPRAY_AREA: 'no_spray_area', AREAS_NOT_FOUND: 'areas_not_found', ITEMS_NOT_FOUND: 'items_not_found',
|
|
NOT_KML_KMZ: 'not_kml_kmz', BLANK_KML_KMZ: 'blank_kml_kmz', JOB_NOT_ASSIGNED: 'job_not_assigned', PRJ_NOT_FOUND: 'prj_not_found',
|
|
UNSUPPORTED_SHAPE_TYPE: 'unsupported_shape_type', EMPTY_SHP_FILE: 'empty_shp_file', DATA_NO_SPRAYON: 'data_no_sprayon',
|
|
INVALID_REQUEST: 'invalid_request', INVALID_PARAM: 'invalid_param', INVALID_INPUT: 'invalid_input', INVALID_VAL_SCHEMA: 'invalid_val_schema',
|
|
INVALID_LONGITUDE: 'invalid_longitude', INVALID_SWATH_WIDTH: 'invalid_swath_width', INVALID_DMS: 'invalid_dms',
|
|
DUPLICATED_VALUE: 'duplicated_value',
|
|
CORRUPTED_ZIP: 'corrupted_zip', INVALID_OBSTACLE_FILE_FORMAT: 'invalid_obstacle_file_format', NO_FILE: 'no_file', FILE_TOO_LARGE: 'file_too_large', DUPLICATED_FILE: 'duplicated_file',
|
|
WRONG_JOB_FILE: 'wrong_job_file', INVALID_AREAS_FILE: 'invalid_areas_file', INVALID_JOB_FILE: 'invalid_job_file',
|
|
|
|
INVALID_PAYMENT_METHOD: 'invalid_payment_method', INVALID_ADDRESS_COUNTRY: 'invalid_address_country',
|
|
PAYMENT_FAILED: 'payment_failed',
|
|
SUBSCRIPTION_NOT_FOUND: 'subscription_not_found', PKG_SUBSCRIPTION_NOT_FOUND: 'pkg_subscription_not_found', TRK_SUBSCRIPTION_NOT_FOUND: 'trk_subscription_not_found',
|
|
PAID_INVOICES_NOT_FOUND: 'paid_invoices_not_found', REACHED_AREA_LIMIT: 'reached_area_limit',
|
|
REACHED_VEHICLES_LIMIT: 'reached_vehicles_limit', PAYMENT_EXPIRED: 'payment_expired', CUST_PM_NOT_FOUND: 'cust_pm_not_found', APP_VENDOR_NOT_FOUND: 'app_vendor_not_found', LOCAL_VENDOR_NOT_FOUND: 'local_vendor_not_found',
|
|
RM_LAST_DEFAULT_PM_NOT_ALLOW: 'rm_last_default_pm_not_allow', RM_ACTIVE_PM_NOT_ALLOW: 'rm_active_pm_not_allow',
|
|
TRIALS_NOT_ENABLED: 'trials_not_enabled', TRIALS_EXPIRED: "trials_expired",
|
|
ONLY_ONE_BILL_ADDR_ALLOWED: 'only_one_bill_address_allowed',
|
|
|
|
// Promo error codes
|
|
PROMO_NOT_FOUND: 'promo_not_found',
|
|
PROMO_IN_USE_VALID_UNTIL_REQUIRED: 'promo_in_use_valid_until_required',
|
|
PROMO_VALID_UNTIL_TOO_SOON: 'promo_valid_until_too_soon',
|
|
PROMO_INVALID_VALID_UNTIL: 'promo_invalid_valid_until',
|
|
PROMO_DUPLICATE_TYPE_PRICEKEY: 'promo_duplicate_type_pricekey',
|
|
PROMO_DUPLICATE_COUPON: 'promo_duplicate_coupon',
|
|
PROMO_OVERLAPPING_DATES: 'promo_overlapping_dates',
|
|
PROMO_COUPON_NOT_FOUND: 'promo_coupon_not_found',
|
|
PROMO_INVALID_COUPON: 'promo_invalid_coupon',
|
|
|
|
// New email verification error codes
|
|
VERIFICATION_CODE_EXPIRED: 'verification_code_expired',
|
|
INVALID_VERIFICATION_CODE: 'invalid_verification_code',
|
|
EMAIL_VERIFICATION_REQUIRED: 'email_verification_required',
|
|
|
|
REPORT_SERVER_ERROR: 'report_server_error',
|
|
HAS_REFERENCE: 'has_reference',
|
|
TEMPLATE_NOT_FOUND: 'template_not_found', TO_NOT_FOUND: 'to_not_found',
|
|
UNKNOWN_APP_ERROR: 'unknown_app_error', UNKNOWN_ERROR: 'unknown_error',
|
|
|
|
APPLICATOR_NOT_FOUND: 'applicator_not_found', COSTING_ITEM_NOT_FOUND: 'costing_item_not_found', INVOICE_NOT_FOUND: 'invoice_not_found', INVOICE_SETTING_NOT_FOUND: 'invoice_setting_not_found', CLIENT_NOT_FOUND: 'client_not_found', JOBS_NOT_FOUND: 'jobs_not_found', CLIENTS_NOT_FOUND: 'clients_not_found',
|
|
CLIENT_OVER_PAID: 'client_over_paid',
|
|
INVOICE_ALREADY_PAID: 'invoice_already_paid', INVOICE_DRAFT: 'invoice_draft', INVOICE_CANCELLED: 'invoice_cancelled', INVOICE_OVERDUE: 'invoice_overdue', INVOICE_VOID: 'invoice_void',
|
|
|
|
JOB_CANNOT_EDIT: 'cannot_edit_job_have_invoice_opened', STATUS_JOB_INVALID: 'status_job_invalid', COSTING_ITEM_IN_USE: 'costing_item_in_use', PARAMS_NOT_EMPTY: 'params_not_empty', INVALID_PUID: 'invalid_parent_user_id', INVALID_CREATED_BY_USER_ID: 'invalid_created_by_user_id',
|
|
PARTNER_SERVICE_UNAVAILABLE: 'partner_service_unavailable', INVALID_ASSIGNMENT: 'invalid_assignment',
|
|
RABBITMQ_MGMT_DISABLED: 'rabbitmq_mgmt_disabled'
|
|
});
|
|
|
|
/*
|
|
Applicator application types
|
|
*/
|
|
const ApplicationTypes = Object.freeze({
|
|
Agricultural: 'agricultural',
|
|
Mosquito_Control: 'mosquito_control',
|
|
Wildfire_Fighting: 'wildfire_fighting',
|
|
Forestry: 'forestry',
|
|
Airborne_Geophysics: 'airborne_geophysics',
|
|
Animal_Control: 'animal_control',
|
|
Photogrammetry: 'photogrammetry',
|
|
UAV_Imaging: 'uav_imaging',
|
|
Other: 'other',
|
|
});
|
|
/*
|
|
Applicator reference sources
|
|
*/
|
|
const RefSources = Object.freeze({
|
|
Web_Search: 'web_search',
|
|
Online_Ads: 'online_ads',
|
|
Trade_Show: 'trade_show',
|
|
Magazine: 'magazine',
|
|
Third_Party: '3rd_party',
|
|
});
|
|
|
|
const InvCreateOption = Object.freeze({ Option1: 'option_1', Option2: 'option_2', Option3: 'option_3' });
|
|
const InvoiceStatus = Object.freeze({ Draft: 'draft', Open: 'open', Paid: 'paid', Void: 'void', Uncollectible: 'uncollectible' });
|
|
const CostingItemType = Object.freeze({ BY_ACRE: 0, BY_HA: 1, BY_AMOUNT: 2 });
|
|
const PaymentMethod = Object.freeze({ Cash: 'cash', Transfer: 'transfer', Debit: 'debit', Credit: 'credit' });
|
|
const InvoiceStatusAction = Object.freeze({ None: 'none', MARK_UNCOLLECTIBLE: 'mark_uncollectible' });
|
|
|
|
// Partner sync status constants
|
|
const SyncStatus = Object.freeze({
|
|
ACTIVE: 'active',
|
|
ERROR: 'error',
|
|
INACTIVE: 'inactive'
|
|
});
|
|
|
|
// Partner health status constants
|
|
const HealthStatus = Object.freeze({
|
|
HEALTHY: 'healthy',
|
|
UNHEALTHY: 'unhealthy',
|
|
DEGRADED: 'degraded'
|
|
});
|
|
|
|
// Partner sync operation constants
|
|
const PartnerOperations = Object.freeze({
|
|
UPLOAD_JOB: 'uploadJobToPartner',
|
|
HEALTH_CHECK: 'healthCheck',
|
|
GET_AIRCRAFT_LIST: 'getAircraftList'
|
|
});
|
|
|
|
// Partner worker task constants
|
|
const PartnerTasks = Object.freeze({
|
|
PROCESS_PARTNER_LOG: 'process_partner_log',
|
|
UPLOAD_PARTNER_JOB: 'upload_partner_job',
|
|
PROCESS_PARTNER_DATA_FILE: 'process_partner_data_file'
|
|
});
|
|
|
|
// Partner Log Tracker Status Constants
|
|
const PartnerLogTrackerStatus = Object.freeze({
|
|
PENDING: 'pending',
|
|
DOWNLOADING: 'downloading',
|
|
DOWNLOADED: 'downloaded',
|
|
PROCESSING: 'processing',
|
|
PROCESSED: 'processed',
|
|
FAILED: 'failed',
|
|
ARCHIVED: 'archived'
|
|
});
|
|
|
|
// SatLoc system type constants
|
|
const SystemTypes = Object.freeze({
|
|
NONE: 'none',
|
|
PLATINUM: 'platinum',
|
|
TITANIUM: 'titanium',
|
|
G4: 'g4',
|
|
BANTAM2: 'bantam2',
|
|
FALCON: 'falcon'
|
|
});
|
|
|
|
// For Flow Controller Types
|
|
const FCTypes = Object.freeze({
|
|
LIQUID: 1,
|
|
DRY: 2
|
|
});
|
|
|
|
// Application data source types
|
|
const DataTypes = Object.freeze({
|
|
SATLOC: 'satloc',
|
|
AGNAV: 'agnav'
|
|
});
|
|
|
|
// Material types for spray applications
|
|
const MatTypes = Object.freeze({
|
|
WET: 'wet',
|
|
DRY: 'dry'
|
|
});
|
|
|
|
// API key service types — which service/integration a key grants access to
|
|
const ApiKeyServices = Object.freeze({
|
|
DATA_EXPORT: 'data_export', // External data consumers (Power BI, ArcGIS, data warehouses)
|
|
PARTNER_API: 'partner_api' // Partner system integrations
|
|
});
|
|
|
|
// Export measurement unit systems
|
|
const ExportUnits = Object.freeze({
|
|
METRIC: 'metric', // SI units (m/s, L/min, L/ha, m, °C) — system default
|
|
US: 'us' // US customary (mph, gal/min, gal/ac, ft, °F)
|
|
});
|
|
|
|
// Partner authentication method constants
|
|
const AuthMethods = Object.freeze({
|
|
API_KEY: 'api_key',
|
|
USERNAME_PASSWORD: 'username_password',
|
|
OAUTH: 'oauth',
|
|
BEARER_TOKEN: 'bearer_token'
|
|
});
|
|
|
|
// Partner codes constants
|
|
const PartnerCodes = Object.freeze({
|
|
SATLOC: 'SATLOC',
|
|
AGIDRONEX: 'AGIDRONEX',
|
|
// Add other partner codes as needed
|
|
});
|
|
|
|
// Promo eligibility constants
|
|
const PromoEligibility = Object.freeze({
|
|
ALL: 'all', // Any customer can use promo
|
|
NEW_ONLY: 'new_only', // Only first-time customers (no subscription history)
|
|
RENEW_ONLY: 'renew_only' // Only returning customers (has subscription history)
|
|
});
|
|
|
|
const PartnerFileExtensions = {
|
|
'.log': PartnerCodes.SATLOC, // SatLoc binary log files
|
|
// Add more partner-specific extensions here as needed
|
|
// '.agx': PartnerCodes.AGIDRONEX,
|
|
// '.dji': PartnerCodes.DJI,
|
|
};
|
|
|
|
const jobInvoiceEditRoles = [UserTypes.APP, UserTypes.APP_ADM];
|
|
const jobInvoiceViewRoles = [...jobInvoiceEditRoles, UserTypes.CLIENT, UserTypes.OFFICER, UserTypes.INSPECTOR, UserTypes.PILOT];
|
|
|
|
const emailRegex = RegExp(/^(([^<>\(\)\[\]\\.,;:\s@"]+(\.[^<>\(\)\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i);
|
|
|
|
module.exports = {
|
|
APTypes, Units, RateUnits, HttpStatus, Fields, RecTypes, UserTypes, FCTypes, DataTypes, MatTypes, Errors, AppStatus, AppProStatus, AssignStatus, TrialTypes,
|
|
DEFAULT_LANG, DEL_APP_IDS, DEFAULT_TRIAL_DAYS, LIMIT_FILE_SIZE_ERR, InvoiceStatus, CostingItemType, InvCreateOption, PaymentMethod, ExportType, jobInvoiceEditRoles, jobInvoiceViewRoles, InvoiceStatusAction, ApplicationTypes, RefSources, emailRegex, SyncStatus, HealthStatus, PartnerOperations, PartnerTasks, SystemTypes, AuthMethods, PartnerCodes, PartnerLogTrackerStatus,
|
|
PartnerFileExtensions, PromoModes, APIActions, PromoEligibility, CouponDuration, StripeErrorTypes,
|
|
ApiKeyServices, ExportUnits
|
|
};
|