### Initialize $.cash Library
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/layouts/Static.html
Initializes the $.cash JavaScript library with user-specific settings and routing information. This setup is required before using $.cash functionalities.
```javascript
var apiSettings = {$api_settings|json_encode};
$(function() {
$.cash.init({
isAdmin: {$isAdmin},
userId: {$userId},
accountName: '{$wa->accountName()|escape}',
appName: '{$wa->appName()}',
routingOptions: {
wa_url: '{$wa_url}',
wa_backend_url: '{$wa_backend_url}',
wa_app_url: '{$wa_app_url}',
wa_app_static_url: '{$wa_app_static_url}'
}
});
});
```
--------------------------------
### Start/Update Import Process
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/plugins/tinkoff/templates/actions/backend/Backend.html
Initiates or updates the data import process. It validates the cash account selection, serializes form data, and sends it to the server. It then starts a polling mechanism to track the import progress.
```javascript
$start_button.on('click', function () {
let $that = $(this);
let $tab_content = $('.js-tab-content-'+ profile_id);
let $cash_account = $('select[name="profiles['+ profile_id +'][cash_account]"]');
if (!$cash_account.val()) {
setTimeout(function () {
$cash_account.removeClass('state-error');
}, 1500);
$cash_account.addClass('state-error');
return;
}
let instance = profiles[profile_id]['progressbar'];
let form_data = $tab_content.find('input, textarea, select').serialize();
$that.addClass('hidden');
$tab_content.find('.js-progressbar').removeClass('hidden');
$tab_content.find('.js-settings-block').addClass('hidden');
$tab_content.find('.js-settings-show').addClass('hidden');
renderText('
[`Подключение...`]');
saveProfile(form_data, function () {
$.post(url, form_data, function (response) {
renderText('');
if (response && response.error) {
$tab_content.find('.js-error-msg').text(response.error);
} else if (response && response.processid) {
process_id = response.processid;
if (instance && response.progress) {
instance.set({ percentage: response.progress });
}
if (response.text_legend) {
renderText(response.text_legend);
}
step(profile_id, instance);
} else {
$tab_content.find('.js-error-msg').text('Server error');
}
}, 'json').error(function () {
$tab_content.find('.js-error-msg').text('Server error');
});
});
});
```
--------------------------------
### Order Import Date Range
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
Displays the date range for importing all historical orders. This is shown only on the first time setup.
```html
All time {sprintf('%s — %s', $shopOrderDateBounds['min']|wa_date:humandate, $shopOrderDateBounds['max']|wa_date:humandate)}
```
--------------------------------
### Order Import Filter for Paid Orders
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
A setting to import only orders that were paid after a specified date. This is part of the initial setup.
```html
Only orders paid after
```
--------------------------------
### Initialize Application State
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/layouts/Static.html
Sets up a global JavaScript object `appState` with essential account, language, URL, and configuration details from the Webasyst environment. This is crucial for client-side scripts to access application context.
```javascript
window.appState = { "accountName": "{$wa->accountName()}", "lang": "{$wa->locale()}", "baseUrl": "{$wa_app_url}", "baseApiUrl": "{$wa_url}api.php", "baseStaticUrl": "{$wa_app_static_url}", "token": "{$token}", "currencies": {$currencies}, "categories": {$categories}, "accounts": {$accounts}, "api_settings": {$api_settings}, "emptyFlow": {json_encode(!empty($emptyFlow))}, "shopscriptInstalled": {json_encode(boolval($wa->shop))}, "isPremium": {json_encode(boolval($isPremium))} };
```
--------------------------------
### Create Cash Flow App Directory
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/README.md
Create the directory for the Cash Flow app within the Webasyst apps folder.
```bash
cd /PATH_TO_WEBASYST/wa-apps/
mkdir cash
git clone git://github.com/1312inc/Webasyst-CashFlow.git ./
```
--------------------------------
### Add Cash Flow App to Configuration
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/README.md
Register the Cash Flow app by adding its entry to the Webasyst configuration file.
```php
'cash' => true,
```
--------------------------------
### Enable Shop-Script Integration Toggle
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
This snippet shows how to initialize a Webasyst Switch component for toggling the Shop-Script integration. It listens for changes to update the integration status.
```javascript
( function($) {
$("#c-switch-ss-integration-core").waSwitch({
change: function(active, wa_switch) {
}
});
})(jQuery);
```
--------------------------------
### JavaScript for Forecasted Sales Switch
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
Initializes a Webasyst Switch component for the forecasted sales setting. The 'change' callback is currently empty.
```javascript
( function($) { $("#c-switch-forecasted-ss-sales").waSwitch({ change: function(active, wa_switch) { } }); })(jQuery);
```
--------------------------------
### Initialize JavaScript Application State
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/layouts/Default.html
Initializes the global `appState` object with account, locale, URL, token, and configuration data. This state is crucial for the frontend to function correctly.
```html
{$wa->appName()} — {$wa->accountName()} {$wa->css()} window.appState = { "accountName": "{$wa->accountName()}", "lang": "{$wa->locale()}", "baseUrl": "{$wa_app_url}", "baseApiUrl": "{$wa_url}api.php", "baseStaticUrl": "{$wa_app_static_url}", "token": "{$token}", "currencies": {$currencies}, "categories": {$categories}, "accounts": {$accounts}, "api_settings": {$api_settings}, "emptyFlow": {json_encode(!empty($emptyFlow))}, "shopscriptInstalled": {json_encode(boolval($wa->shop))}, "isPremium": {json_encode(boolval($isPremium))} };
```
--------------------------------
### Import Process Step
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/plugins/tinkoff/templates/actions/backend/Backend.html
Manages the step-by-step import process by polling the server for status updates. It uses `setInterval` to periodically send requests and updates the UI based on the response, including progress bars and status messages. It redirects to the account page upon successful import.
```javascript
let step = function (profile_id, $progressbar) {
timer = setInterval(function () {
$.post(url, { processid: process_id, profile_id: profile_id }, function (response) {
renderText('');
if (response && response.error) {
$('.js-tab-content-'+ profile_id).find('.error-msg').text(response.error);
} else if (response && response.ready) {
clearInterval(timer);
if ($progressbar) {
$progressbar.set({ percentage: 100 });
}
if (response.text_legend) {
renderText(response.text_legend);
}
setTimeout(function () {
let cash_account = response.cash_account_id || $('select[name="profiles['+ profile_id +'][cash_account]"]').val();
renderText('');
$('.progressbar').hide();
window.location = window.appState.baseUrl +'account/'+ cash_account +'?show_success_import_hint=1';
}, 1000);
} else {
if ($progressbar && response && response.progress) {
$progressbar.set({ percentage: response.progress });
}
if (response.text_legend) {
renderText(response.text_legend);
}
}
}, 'json');
}, 2000);
};
```
--------------------------------
### Initialize Webasyst Cashflow App State
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/client/index.html
Configures the global `window.appState` object with essential application settings. This includes UI mode, account information, localization, API URLs, and feature flags. It also conditionally initializes an event emitter for mobile mode.
```javascript
window.appState = { "webView": <%- mode === 'mobile' %>, "accountName": "accountName", "lang": "ru\_RU", "baseUrl": "/", "baseApiUrl": "/api.php", "baseStaticUrl": "/wa-apps/cash/", "token": "<%= token %>", "currencies": <%- currencies %>, "categories": <%- categories %>, "accounts": <%- accounts %>, "api\_settings": <%- settings %>, "emptyFlow": true, "shopscriptInstalled": true, "isPremium": true }; <% if (mode === 'mobile'){ %> window.emitter = mitt(); <% } %> <% if (mode === 'desktop'){ %>
<% } %> <% if (mode === 'mobile'){ %>
<% } %>
```
--------------------------------
### JavaScript Data Fetching and Widget Initialization
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/widgets/balanceflow/templates/Default.html
Fetches data for the Balance Flow Widget and initializes it. This script should be used when the Webasyst UI version is 2.0.
```javascript
import { fetchData } from '{$url_root}wa-apps/cash/widgets/balanceflow/js/balanceFlowWidget.js';
fetchData({ baseUrl: '{$url_root}', token: '{$token}' });
window.addEventListener('balanceflowWidgetDataFetchFinished', function (e) {
e.detail.makeBallanceFlowWidget({
container: document.querySelector(".cash-widget-{$info['id']}"),
data: e.detail.result,
currencyCode: "{$currency_code}",
currencySign: "{$currencies[$currency_code]->getSign()}",
size: "{$info['size']}",
locale: "{$locale}".replace("_", "-"),
localeMessages: {
arrowUp: '[`Going positive!`]',
arrowDown: '[`Cash gap is coming`]',
month: '[`m`]',
noAccess: '[`noAccess`]'
}
})
}, { once: true });
(function () {
setTimeout(function () {
try {
DashboardWidgets[{$info['id']]].renderWidget();
} catch (e) {
}
}, 10 * 60 * 1000);
})();
```
--------------------------------
### Shop Settings Form Handling
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
Handles form submission, toggling elements, and updating UI based on user input for shop settings. Includes AJAX post for saving settings and real-time UI updates.
```javascript
'use strict';
(function () {
var $ssform = $('#cash-shopscript-settings'),
formData = $ssform.serialize();
if ($ssform.length) {
$ssform
.on('submit.cash', function (e, data) {
var $saved = $(""),
$loading = $(""),
$button = $ssform.find('[type="submit"]');
e.preventDefault();
formData = $ssform.serialize();
$button.after($loading);
$.post('?module=shop&action=settings', formData, function (html) {
$loading.remove();
$button.after($saved);
setTimeout(function () {
$saved.remove();
window.location.reload();
}, 131.2);
})
})
.on('click.cash', '[data-cash-shop-configure-actions]', function (e) {
e.preventDefault();
var $this = $(this),
type = $this.data('cash-shop-configure-actions'),
$w = $ssform.find('[data-cash-shop-configure-actions-' + type + ']');
if ($w.length) {
$w.toggle();
}
})
.on('change.cash', '[data-cash-category-color-icon] select', function () {
var $select = $(this),
$w = $select.closest('[data-cash-category-color-icon]'),
$color = $w.find('i.color'),
$selected = $select.find(':selected');
$color.css('background', $selected.data('cash-category-color'));
})
.on('change.cash', '[name="shopscript_settings[enableForecast]"]', function (e) {
$ssform.find('[data-cash-settings="forecast-variants"]').toggle($(this).is(':checked'));
})
.on('change.cash', '[name="shopscript_settings[accountId]"]', function (e) {
var $this = $(this),
$error = $this.closest('.field').find('.errormsg');
$error.hide();
$.post('?module=json&action=checkShopCurrency', {
account: $this.val()
}, function (r) {
if (r.status === 'fail') {
$error.text(r.errors).show();
}
}, 'json')
})
.on('change.cash', ':input', function (e) {
$ssform.find('[data-cash-shop-save-button]').addClass(formData != $ssform.serialize() ? 'yellow' : 'green');
})
.on('click.cash', '[data-cash-shop-action="rerun-import"]', function (e) {
e.preventDefault();
$.get('?module=shop&action=resetImportDialog', function(dialogHtml) {
$.waDialog({
html: dialogHtml,
onOpen: function ($dialogWrapper, d) {
var $errorMsg = $dialogWrapper.find('.errormsg'),
$submitButton = $dialogWrapper.find('.js-ok');
setTimeout(function () {
$dialogWrapper.find('[name="code"]').trigger('focus');
}, 13.12);
$errorMsg.hide();
$dialogWrapper.find('[name="code"]').on('keypress', function (e) {
if (e.key === "Enter") {
e.preventDefault();
$submitButton.trigger('click');
}
});
$submitButton.after($.cash.$loading).on('click.cash', function (e) {
e.preventDefault();
$.post('?module=shop&action=resetImport', $dialogWrapper.find('form').serialize(), function (r) {
$.cash.$loading.remove();
if (r.status === 'ok') {
d.close();
window.location.reload();
} else {
$errorMsg.text(r.errors.join(' ')).show();
}
}, 'json');
});
$dialogWrapper.find('.js-close').on('click.cash', function (e) {
d.close();
});
}
});
})
})
.on('change.cash', '[name="shopscript_settings[enabled]"]:checkbox', function (e) {
var $setW = $ssform.find('[data-cash-shop-settings-wrapper]');
if ($(this).is(':checked')) {
$setW.removeClass('c-shop-settings-wrapper-disabled');
} else {
$setW.addClass('c-shop-settings-wrapper-disabled');
}
})
.on('click.cash', '.firstTimeHiddenBlockToggler', function (e) {
e.preventDefault();
$ssform.find('.firstTimeHiddenBlock').toggle();
});
$ssform.find('select').trigger('change.cash');
var $welcome = $('#cash-welcome-shop-start');
if ($welcome.length) {
var $allPeriod = $ssform.find('[name="import_period"]:first'),
$afterPeriod = $ssform.find('[name="import_period"]:last'),
datepicker_options = {
changeMonth: true,
changeYear: true,
shortYearCutoff: 2,
dateShowWeek: false,
showOtherMonths: true,
selectOtherMonths: true,
stepMonths: 1,
numberOfMonths: 1,
gotoCurrent: true,
constrainInput: false,
dateFormat: "yy-mm-dd",
onSelect: function(date) {
$afterPeriod.prop('checked', true);
updateImportOrderCount(date);
},
},
$datePicker = $ssform.find('[name="import_period_after"]');
$datePicker.datepicker(datepicker_options);
var updateImportOrderCount = function (after) {
$.post('?module=json&action=updateImportOrderCount', {
after: after
}, function (r) {
if (r.status !== 'fail') {
$welcome.val($_( 'Import ' + parseInt(r.data) + ' paid orders'))
}
}, 'json')
};
$afterPeriod.on('click.cash', function (e) {
updateImportOrderCount($datePicker.val());
});
$allPeriod.on('click.cash', function (e) {
updateImportOrderCount();
});
$welcome.on('click.cash', function (e) {
e.preventDefault();
var $button = $(this),
$progress = $('#c-welcome-import'),
$progressBar = $progress.find('.progressbar'),
$progressLoading = $progress.find('[data-cash-shop-import-progress-icon="loading"]'),
$progressCounts = $progressLoading.find('[data-cash-shop-import-progress-counts]'),
$progressSuccess = $progress.find('[data-cash-shop-import-progress-icon="success"]'),
$progressError = $progress.find('[data-cash-shop-import-progress-icon="progre']
});
}
}
})();
```
--------------------------------
### Download Error Log Link
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/csv/view.html
Conditionally displays a link to download the error log if the import entity has errors.
```html
{if $filter->entity->getErrors()}* [[\`Download error log\`]](?module=import&action=csvDownloadErrors&id={$filter->identifier}){/if}
```
--------------------------------
### Load Backend Layout Plugins
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/layouts/Default.html
Iterates through registered backend layout plugins and loads their respective JavaScript files. This allows for extending the backend interface.
```html
{\* @event backend_layout.%plugin_id%.js *} {foreach $backend_layout_plugins as $plugin_name => $backend_layout_plugin} {$backend_layout_plugin.js|default:''} {/foreach}
```
--------------------------------
### Shop Settings Validation and Import Process
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
Handles form submission for shop settings validation and initiates a long action for importing data. Includes progress bar updates and error display.
```javascript
($progressBar.length && $progressBar.data('progressbar')) || ($progressBar.waProgressbar({ "color": "var(--green)", "text-inside": true }), $progressBar.data('progressbar')); var progressInstance = $progressBar.data('progressbar'); $.post('?module=shop&action=settingsValidate', $ssform.serialize(), function (r) { var $errors = $ssform.find('[data-cash-shop-errors]'); $errors.find('.box').empty(); if (r.status === 'fail') { $errors.show(); var errors = []; for(var error in r['errors']) { errors.push(r['errors'][error]); } $errors.find('.box').html(errors.join(' ')); } else { $errors.hide(); $button.prop('disabled', true).hide(); var long = $.wa.kmLongAction(); long.start({ process_url: '?module=shop&action=importProcess', parallel: 2, debug: true, start: { data: { 'period': $('[name="import_period"]:checked').val(), 'period_after': $datePicker.val() }, onStart: function (r) { $button.hide(); $progressLoading.show().siblings().hide(); }, onSuccess: function (r) { $progressBar.show(); progressInstance.set({ percentage: 10 }); }, onError: function (r) { $progressError.show().siblings().hide(); $progressError.find('em').text(r.error); $button.prop('disabled', false).show(); } }, step: { onProgress: function (r) { progressInstance.set({ percentage: Math.round( r.progress * 0.9) + 10 }); $progressCounts.text(r.passed_orders + ' / ' + r.total_orders) }, onReady: function (r) { $progressSuccess.show().siblings().hide(); progressInstance.set({ percentage: Math.round(r.progress) }); window.location = window.appState.baseUrl + 'account/' + $ssform.find('[name="shopscript_settings[accountId]"]').val() + '?show_ss_import_hint=1'; }, onError: function (r) { $progressError.show().siblings().hide(); $progressError.find('em').text(r.error); $button.prop('disabled', false).show(); } } }); } });
```
--------------------------------
### Premium App Icon CSS
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/upgrade/Upgrade.html
CSS for styling the premium app icon, including its position, z-index, height, and background image.
```css
.c-premium-appicon { position: relative; z-index: 10; height: 9rem; background: url('{$wa_url}wa-apps/cash/img/cash.png') no-repeat center / 8rem; }
```
--------------------------------
### Manage Import Progress Steps
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/Import.html
This JavaScript code manages the visual progress indicator for the import steps. It updates the UI to show completed and current steps based on the provided step number. This is typically triggered after a successful file upload or configuration.
```javascript
$w.on("stepChange.cash", function (e, stepN) {
stepN--;
$importProgress.find("li").removeClass().each(function (index) {
if (index < stepN) {
$(this).addClass("completed");
}
if (index == stepN) {
$(this).addClass("current");
}
});
});
```
--------------------------------
### Profile Selection Handling
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/plugins/tinkoff/templates/actions/backend/Backend.html
Handles clicks on profile elements to select a profile. It updates the UI to reflect the selected profile and shows the corresponding tab content. It also displays the last update date if available.
```javascript
$('#js-profile-c').on('click', 'div.c-profile', function (e) {
profile_id = $(this).find('a').data('profile-id');
$('#js-profile-c > div.c-profile').removeClass('c-selected');
$(this).addClass('c-selected');
if (profile_id) {
$('[name="profile_id"]').val(profile_id);
$('[class*=js-tab-content').addClass('hidden');
$('.js-tab-content-'+ profile_id).removeClass('hidden');
if (profiles.hasOwnProperty(profile_id)) {
let $up_dt = $('.js-update-date');
if (profiles[profile_id].hasOwnProperty('update_date') && profiles[profile_id]['update_date']) {
$up_dt.text(profiles[profile_id]['update_date']);
$up_dt.closest('strong.hint').removeClass('hidden');
} else {
$up_dt.closest('strong.hint').addC
```
--------------------------------
### Main Pagination Logic
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/include/pagination.html
This snippet contains the core logic for rendering pagination controls. It conditionally displays total rows, navigation links (previous, page numbers, next), and records per page options based on the presence and values of variables like $pagination, $show_total_rows, $current_page, $base_url, $limit, and $show_records_on_page.
```HTML (Templating)
{if count($pagination) > 1 || $show_records_on_page}
{if $show_total_rows}[`Total`]: {$total_rows}{/if} {if count($pagination) > 1} {if $current_page != 1} [[\`prev\`]]({$base_url}/{$start-$limit}/{$limit}/) {/if} {foreach $pagination as $page => $offset} {$page} {else} ... {/if} {/foreach} {if $current_page != $page} [[\`next\`]]({$base_url}/{$start+$limit}/{$limit}/) {/if} {/if}
{if $show_records_on_page}
[`Show`] {foreach $records_on_page as $onpage} {$onpage} {/foreach} [`at page`]
{/if} {/if}
```
--------------------------------
### JavaScript for Transaction List and Import Deletion
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/csv/view.html
Initializes the transaction list, loads transactions, and handles the deletion of a CSV import via an AJAX POST request. If deletion is successful, it redirects to the root hash; otherwise, it logs errors.
```javascript
'use strict';
(function () {
var $w = $('#cash-imports-page'),
$transactionList = $('[data-cash-wrapper="transaction-list"]'),
filterId = '{$filter->identifier}',
filterType = '{$filter->type}',
startDate = '{$startDate}',
endDate = '{$endDate}';
$.cash.loadTransactions(startDate, endDate, filterId, filterType, $transactionList);
// $.cash.loadGraphData(startDate, endDate, filterId, filterType, '#cash-chart');
$w.on('click', '[data-csv-import-action="delete"]', function (e) {
e.preventDefault();
$.post(
'?module=import&action=csvDelete',
{ id: filterId },
function (r) {
if (r.status === 'ok') {
window.location.hash = '#/';
} else {
$.cash.log(r.errors.join("\n"));
}
},
'json'
);
});
}());
```
--------------------------------
### Webasyst Cashflow Upgrade Logic (Smarty)
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/upgrade/Upgrade.html
Smarty template logic to determine premium status, cloud status, and construct the upgrade URL. This logic is used to conditionally display upgrade buttons and pricing information.
```smarty
{$\_is\_premium = cashHelper::isPremium()}
{$\_is\_cloud = cashHelper::isCloud()}
{$\_premium\_pricing = cashHelper::getPremiumPricing()}
{$\_upgrade\_url = '[\`https://www.webasyst.com/my/buy/upgrade-to-premium/cash/\]'|cat:'?domain='|cat:str\_replace('http://','',str\_replace('https://','',$wa->domainUrl()))}
{capture "getpremiumbutton"}
{if !$\_is\_premium}
[{if $\_is\_cloud}\[\`Upgrade to premium\`\]{else}{$\_premium\_pricing.special\_button|default:'\[\`Upgrade to premium\`\]'}{/if}]({$_upgrade_url})
#### {if $\_is\_cloud} {if !empty($\_premium\_pricing.compare\_price)}{$\_premium\_pricing.compare\_price}{/if} \[\`All inclusive in the cloud\`\] {else} {if !empty($\_premium\_pricing.upgrade\_compare\_price)}{$\_premium\_pricing.upgrade\_compare\_price}{/if} {if !empty($\_premium\_pricing.upgrade\_price)} {$\_premium\_pricing.upgrade\_price} — \[\`upgrade basic → premium\`\]
{/if} {if !empty($\_premium\_pricing.compare\_price)}{$\_premium\_pricing.compare\_price}{/if} {$\_premium\_pricing.price} — \[\`new premium license\`\] {/if}
{if $\_is\_cloud} \[\`In Webasyst Cloud, simply upgrade to the **Premium** plan and get all premium features at once with no extra purchase.\`\] {sprintf('[\[\`Or get [new license](%s) for the Custom plan.\`\]', $\_upgrade\_url)} {else} {if !empty($\_premium\_pricing.special)} **\[\`One-time payment, not a subscription!\`\]**
{sprintf('[\[\`%s intro offer for upgrading existing app license to the premium version\`\]', sprintf('%s', $\_premium\_pricing.special\_color, $\_premium\_pricing.special))} — **{date('Y.m')} \[\`special offer!\`\]** {else} \[\`Per-server license for the entire company. Unlimited users, all the premium features, and free updates forever.\`\] {/if} {/if}
{/if}
{/capture}
```
--------------------------------
### Initialize Report Stream Chart
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/report/internal/ReportStream.html
Import and initialize the reportStream function to render a chart. Ensure the correct data, locale, and target element ID are provided. This is typically used within an HTML template.
```html
{if $wa->locale() !== 'en_US'} {/if} import reportStream from "{$wa_app_static_url}js/reports/reportStream.js?v={$wa->version()}"; reportStream('chartdiv_stream', {$data|json_encode}, '{$wa->locale()}');
```
--------------------------------
### Report Period Navigation
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/report/internal/ReportDds.html
Provides a list of report periods for navigation, highlighting the currently selected period. Includes JavaScript for initializing a dropdown.
```html
* {$currentPeriod->getName()}
{foreach array_reverse($reportPeriods) as $reportPeriod}
* isEqual($reportPeriod)}class="selected"{/if}> [{$reportPeriod->getName()|escape}]({$wa_app_url}report/dds/type={$type->id}&year={$reportPeriod->getValue()})
{/foreach}
( function($) { $("#c-dds-year-dropdown").waDropdown(); })(jQuery);
```
--------------------------------
### Initiate Tinkoff Connection
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/plugins/tinkoff/templates/actions/backend/Backend.html
Handles the connection process with Tinkoff. It redirects the user to a Tinkoff authorization URL or displays errors if the connection fails. It also reloads the page if profiles are successfully retrieved.
```javascript
function tinkoffConnect($button, param) {
$button.addClass('disabled');
$.get('?plugin=tinkoff&module=auth'+ (param ? '&add=1' : ''), function (data) {
data = (data.hasOwnProperty('data') ? data.data : data);
if (data.redirect_url) {
window.location.href = data.redirect_url;
} else if (data.error_description) {
alert(data.error_description);
} else if (data.errors) {
$('.js-connect-error').text(data.errors.join(' ').replace(/[,\s]+$/m, ''));
} else if (data.profiles) {
window.location.reload();
}
});
}
```
--------------------------------
### Create New Category via Prompt
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/csv/form.html
Handles the creation of new income or expense categories. Prompts the user for a new category name and sends a POST request to save it. Updates dropdowns with the new category.
```javascript
}).on('change.cash', '[data-cash-csv-import-conditions-category] select, [name="import[category][single][income][column]"] , [name="import[category][single][expense][column]"]', function(e) {
var $this = $(this),
$selected = $this.find(':selected'),
val = $selected.val(),
newCatName = '',
type = '';
if (val == {cashImportResponseCsv::NEW_INCOME_ID}) {
newCatName = prompt($\_('New income category: '));
type = '{cashCategory::TYPE_INCOME}';
} else if (val == {cashImportResponseCsv::NEW_EXPENSE_ID}) {
newCatName = prompt($\_('New expense category: '));
type = '{cashCategory::TYPE_EXPENSE}';
}
if (newCatName && type) {
$this.prop('disabled', true);
$.post('?module=category&action=save', { category: { type: type, name: newCatName } }, function (r) {
$this.prop('disabled', false);
if (r.status === 'ok') {
var $optgroup = $form.find('[data-cash-categories-optgroup="' + type + '"]'),
$expenses = $form.find('[name="import[category][single][expense][column]"]'),
$incomes = $form.find('[name="import[category][single][income][column]"]'),
option = '';
if ($optgroup.length) {
$optgroup.find('option:first').after(option);
}
$expenses.find('option:nth(1)').after(option);
$incomes.find('option:nth(1)').after(option);
$this.find('option[value="' + r.data.id + '"]').attr('selected', 'selected');
}
}, 'json');
}
})
```
--------------------------------
### Conditional Header for Single App Mode
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/layouts/Default.html
Renders a specific header for the user when the application is running in single-app mode. Includes JavaScript to adjust container styling.
```html
{if $wa->isSingleAppMode()}
{$wa->headerSingleAppUser()}
$(function () { $('#wa-single-app-nav-container')
.parent()
.css({ 'z-index': 100500, 'overflow': 'visible' }); }); {/if}
```
--------------------------------
### Display Order Financial Summary
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/include/shop-legacy/backend_order.aux_info.html
This snippet iterates through and displays income, expense, and profit counts and totals for an order. It also shows the total delta and provides links to add new transactions or view all associated transactions. It uses conditional logic for locale-specific text.
```html
{\n\t$\_
smthngshwn = 0\n} {if $info->incomeCount} {$\_
smthngshwn = 1}* {implode(' ', $info->income)} ({$info->incomeCount})
{/if} {if $info->expenseCount} {$\_
smthngshwn = 1}* {implode(' ', $info->expense)} ({$info->expenseCount})
{/if} {if $info->profitCount} {$\_
smthngshwn = 1}* {implode(' ', $info->profit)} ({$info->profitCount})
{/if} {if $info->delta} {$\_
smthngshwn = 1}* {if $wa->locale() == 'ru\_RU'}Итого{else}Total{/if} {implode(' ', $info->delta)}
{/if}
{if !$\_
smthngshwn}
{if $wa->locale() == 'ru\_RU'}С заказом еще не связано ни одной денежной операции.{else}No transactions are linked with the order yet.{/if}
{/if}
[\\+ {if $wa->locale() == 'ru\_RU'}Доход{else}Income{/if}]({$info->link}?addtransaction=income) [− {if $wa->locale() == 'ru\_RU'}Расход{else}Expense{/if}]({$info->link}?addtransaction=expense)
[{\\+} {if $wa->locale() == 'ru\_RU'}Все операции{else}View transactions{/if} ({$info->incomeCount + $info->expenseCount + $info->profitCount})]({$info->link})
```
--------------------------------
### Responsive Chart CSS for TV Dashboard
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/widgets/balanceflow/templates/Default.html
Applies CSS to make the cash widget chart responsive on the TV dashboard for Webasyst UI 2.0.
```css
body.tv .cash-widget-{$info['id']} .cash-widget-chart { width: auto !important; height: auto !important; }
```
--------------------------------
### Initialize Report Categories
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/report/internal/ReportDdsCategories.html
Initializes the report categories using provided data, locale, year, and category values. This script should be included in your HTML to enable interactive report visualizations.
```javascript
import reportCategories from "/static/js/reports/reportCategories.js?v=1.0.0";
const data = {"all_income":[],"all_expense":[]};
const categories = {};
const year = Number(new URL(window.location).pathname.split('/').pop().split('=')[1]) || new Date().getFullYear();
reportCategories(data, 'en_US', year, Object.values(categories));
```
--------------------------------
### jQuery Dropdown Initialization
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/report/internal/ReportDdsCategories.html
Initializes a Webasyst dropdown component for the year selection. This snippet assumes jQuery and the Webasyst UI library are available.
```javascript
( function($) {
$("#c-dds-year-dropdown").waDropdown();
})(jQuery);
```
--------------------------------
### CSV Import Date Format Selection
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/csv/form.html
Handles user interaction for selecting or entering a custom date format. It prompts the user for a format if none is selected and triggers a change event.
```javascript
(function ($) {
var $dateFormatW = $('[name="import[datetime]"]');
var $form = $('#cash-flow-import-form');
$dateFormatW.on('change.cash', 'select', function (e) {
var $this = $(this),
$selected = $this.find(':selected'),
value = $selected.val();
if (!value) {
var format = prompt($_( 'Enter format'));
if (format) {
$selected.before('')
.removeAttr('selected');
$this.trigger('change.cash');
}
} else {
$form.find('[name="import[datetime]"]').trigger('change.cash');
}
});
$form.find('[name="import[datetime]"], [name="import[amount][single][column]"]').trigger('change.cash');
$('#c-import-step-1').hide();
}(jQuery))
```
--------------------------------
### Initialize Date Range Toggle with Update Functionality
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/report/includes/DateRange.html
Initializes the date range toggle component and sets up event listeners for date updates. Use this when you need to capture selected dates and redirect the user.
```javascript
import renderRangeToggle from '{$wa_app_static_url}js/reports/rangeToggle.js?v={$wa->version()}';
$(function () {
renderRangeToggle('.range-container', [-365, -90, -30, 30, 90, 365, 1095, 1825], updateDates);
$('.range-container button').on('click', updateDates);
function updateDates () {
const from = $('.range-container [name="from"]').val();
const to = $('.range-container [name="to"]').val();
window.location = 'from=' + from + '&to=' + to;
}
});
```
--------------------------------
### Automatic Average Daily Sales Calculation
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
A checkbox to enable automatic calculation of average daily sales based on the last 30 days of data. The 'checked' attribute is set based on the isAutoForecast() method.
```html
isAutoForecast()}checked{/if} />
Calculate average daily sales automatically (≈{$avg}/day based on the data for the last 30 days)
```
--------------------------------
### Confirm and Reset Tinkoff Import
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/plugins/tinkoff/templates/actions/backend/Backend.html
Provides a confirmation dialog before performing a full reset of the Tinkoff import. This is a critical action intended for situations where a complete restart is necessary.
```javascript
$('.js-tinkoff-reset').on('click', function (e) {
e.preventDefault();
$.waDialog.confirm({
title: 'Не совершайте ошибку',
text: 'Перезапускать импорт с нуля имеет смысл, только если что-то пошло совсем не так. Например, если нужно кардинально сменить режим работы и переключить плагин из авто-режима в селф-сервис или наоборот.',
success_button_title: 'Начать все с начала',
success_button_class: 'danger',
cancel_button_title: 'Ничего не менять',
cancel_button_class: 'light-gray',
onSuccess: function () {
$.get('?plugin=tinkoff&module=reset', function () {
window.location.reload();
});
}
});
});
```
--------------------------------
### Enable Tinkoff Self-Service Mode
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/plugins/tinkoff/templates/actions/backend/Backend.html
Makes the token field visible, indicating that the plugin is being switched to self-service mode.
```javascript
$('.js-on-self-mode').on('click', function (e) {
e.preventDefault();
$('.js-token-field').removeClass('hidden');
});
```
--------------------------------
### CSV Import Account Mapping Row
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/csv/form.html
HTML template for rendering a row in the CSV import form that maps a column to a financial account. Includes an option to skip rows.
```html
${columnValue}
=>
${transactions}
```
--------------------------------
### Import Name Display
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/csv/view.html
Displays the name of the import, escaped for safe rendering in HTML.
```html
{$filter->name|escape}
```
--------------------------------
### Initialize Report Sankey Chart
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/report/internal/ReportSankey.html
Initializes a Sankey chart using the reportSankey JavaScript function. Ensure the necessary JS file is imported and data is correctly formatted.
```javascript
import reportSankey from "/static/js/reports/reportSankey.js?v=1.0.0";
reportSankey('chartdiv_sankey', {"data": []}, 'en_US', '[`All currencies`]');
```
--------------------------------
### Order Import Update Notice
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/shop/ShopSettings.html
Informs the user that changes to order import settings apply only to new orders. It advises on how to update existing data by deleting and re-importing.
```html
All changes to the order import setup will be applied to new orders only. To update data for existing orders and transactions that had been imported already, delete all existing transactions manually and then [re-start the integration from scratch](%s).
```
--------------------------------
### Handle CSV File Upload and Preview
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/Import.html
This JavaScript code handles the change event for a file input, submitting the form and processing the response to display a preview of the imported data. It's used for the initial step of uploading a CSV file for import.
```javascript
var $w = $("#cash-import-page"), $importProgress = $w.find(".c-import-progress"), $uploadForm = $("#cash-import-upload-form"), $uploadIframe = $("#cash-upload-file"), $step2 = $("#c-import-step-2"), $loading = $("
"); $uploadForm.on("change", "[name=\"upload[file]\"]", function () {
$uploadForm.append($loading);
$uploadForm.trigger("submit");
$uploadIframe.one("load", function () {
$loading.remove();
var html = $(this).contents().find("body").html();
$step2.html(html);
$w.trigger("stepChange.cash", 2);
});
});
```
--------------------------------
### Premium Feature Card CSS
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/upgrade/Upgrade.html
CSS for styling premium feature cards, including border-radius, background, margin, and padding. Includes a specific style for half-width cards.
```css
.c-premium-feature { border-radius: 0.75rem; background: var(--background-color-blank); margin-bottom: 1.5rem; padding: 1.5rem 2rem; } .c-premium-feature.halfwidth { width: 40%; margin-bottom: 0; padding-bottom: 0.5rem; } .c-premium-feature.halfwidth h3 { fonc-size: 1.25rem; } .c-app-inline-badge { max-height: 50px; width: auto; margin-bottom: 0.5rem; } @media screen and (max-width: 760px) { .c-premium-feature.halfwidth { width: 100%; } }
```
--------------------------------
### Datepicker Initialization
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/plugins/tinkoff/templates/actions/backend/Backend.html
Configures a jQuery datepicker widget with specific options, including date format and month/year selection. It also sets a callback to update an import period field when a date is selected.
```javascript
let datepicker_options = {
changeMonth: true,
changeYear: true,
shortYearCutoff: 2,
dateShowWeek: false,
showOtherMonths: true,
selectOtherMonths: true,
stepMonths: 1,
numberOfMonths: 1,
gotoCurrent: true,
constrainInput: false,
dateFormat: 'yy-mm-dd',
onSelect: function (date) {
$(this).closest('div').find('[name$="[import_period]"]').prop('checked', true).val(date);
}
};
let $date_picker = $('[name$="[begin_import_period]"]');
$date_picker.datepicker(datepicker_options);
```
--------------------------------
### Fetch Unique Column Values and Map Them
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/import/csv/form.html
Fetches unique values for a selected column and populates a mapping interface. It allows users to map these values to existing categories or create new ones. Stores relations in localStorage.
```javascript
}).on('change.cash', '[data-cash-csv-import-action="fetch-column-data"]', function (e) {
var $this = $(this), name = $this.find(':selected').text(), scope = $this.data('cash-csv-import-conditions'), dataScope = 'data-cash-csv-import-conditions-' + scope, $wrapper = $('table[' + dataScope + ']'), $template = $('script[' + dataScope + ']');
$wrapper.empty();
fetchColumnUniqueValues(name, function (r) {
if (r.status === 'ok') {
if (!r.data['{{cashImportCsvAbstractValidator::UNIQUE_VALUES}}']) {
return;
}
$.each(r.data.{{cashImportCsvAbstractValidator::UNIQUE_VALUES}}, function (index, columnValue) {
if (!transactionCounts[name][columnValue]) {
return;
}
var $tpl = $template.tmpl({
columnValue: columnValue,
sources: data[scope],
scope: scope,
translate: {
'Expense': $\_('Expense'),
'Income': $\_('Income'),
'Skip rows with this value': $\_('Skip rows with this value')
},
transactions: transactionCounts[name][columnValue] + ' ' + $\_('transactions')
}).on('change', 'select', function () {
var relations = JSON.parse(localStorage.getItem('relationsStorage') || '{}'), optionValue = $(this).find('option:selected').val();
// Exclude Skip rows and New Category options
if (['0', '-1111111111', '-2222222222'].includes(optionValue)) {
delete relations[columnValue]
} else {
relations[columnValue] = $(this).find('option:selected').text();
}
localStorage.setItem('relationsStorage', JSON.stringify(relations));
}).appendTo($wrapper);
var relationsFromStorage = JSON.parse(localStorage.getItem('relationsStorage') || '{}');
if (relationsFromStorage[columnValue]) {
var $select = $tpl.find('select'), val = $select.find("option").filter(function () { return $(this).text() == relationsFromStorage[columnValue]; }).val();
$select.val(val).change();
}
});
} else {
alert(r.errors.join("\n"));
}
});
})
```
--------------------------------
### Cash Flow Report Title and Sandbox Message
Source: https://github.com/1312inc/webasyst-cashflow/blob/master/templates/actions/report/internal/ReportDds.html
Displays the main title for the cash flow report and a message if sandbox accounts are not included.
```html
[`Cash flow report`]
========================
{if $is_imaginary}
[\`Sandbox accounts are not displayed in the cash flow report.\`]
{/if}
```