Files
objecttothisandClaude Sonnet 4.6 74e825ba6f feat(stock-locations): add default location and sort order support (#4643)
Refactor Stock_location model to camelCase naming and introduce
is_default and sort_order fields with full migration, UI, and
item-sync support. Multiple follow-up fixes consolidated.

Database
- Add is_default (TINYINT, backfilled to oldest non-deleted row) and
  sort_order (nullable unsigned TINYINT unique, dense 0..N-1) columns
  via new migration; MySQL 5.7-compatible backfill using user variables
  instead of ROW_NUMBER(); down() drops both columns

Model
- Rename show_locations → showLocations (camelCase convention)
- Add getDefaultLocationId(), setDefaultLocation(), saveSortOrder();
  validate location existence before setting as default
- delete() compacts sort_order via two-pass CASE update to avoid
  collisions after prior reorders
- Atomic sort_order assignment via explicit SQL COUNT query

Controller / Config
- Modularize save logic into sanitizeSubmittedLocations(),
  deleteRemovedLocations(), saveSubmittedLocations(),
  saveLocationOrderAndDefault(); wrap in single transaction
- Support stock_location_new inputs for new-row creation
- Resolve new-* ID placeholders to real IDs post-save
- Abort loop on save failure; default missing POST arrays to []
- Validate that at least one location array is non-empty

Views
- Add Default column with center-aligned radio buttons; disable for
  unsaved rows; use attr() instead of data() for location IDs
- Escape dynamic location IDs against XSS in all affected partials
- form_count_details.php: fall back to default location when current
  is undefined; guard quantity input similarly
- Add aria-label to default radio inputs

Libraries / Items
- Widen Item_lib::get_item_location() and get_stock_destination() to
  nullable return types
- Guard null location_id in Items::getRow() and getGenerateBarcodes()
- Item::get_multiple_info(): accept ?int $location_id; short-circuit
  with where('item_id', -1) instead of always-false where('1','0')

i18n
- Add stock_location_default, stock_location_default_header,
  stock_location_name_header across all locale files

Tests
- Stock_locationTest: getDefaultLocationId, setDefaultLocation,
  saveSortOrder, delete compaction, saveValue; rename to
  testMethod_Scenario convention
- Add ConfigControllerTest / StockLocationsControllerTest with
  AdminAuthTrait covering CRUD, reorder, default assignment, and
  malformed/empty/blank payload validation
- DatabaseBootstrapTrait-based setup for ItemTest and Stock_locationTest

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-10-27 14:36:34 +04:00

349 lines
35 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
return [
'address' => 'Адреса організації',
'address_required' => 'Адреса організації - обов\'язкове поле.',
'all_set' => 'Усі дозволи на файли встановлені правильно!',
'allow_duplicate_barcodes' => 'Дозволити дублювати штрих-коди',
'apostrophe' => 'Апостроф',
'backup_button' => 'Резервна копія',
'backup_database' => 'База даних резервного копіювання',
'barcode' => 'Штрих-код',
'barcode_company' => 'Назва організації',
'barcode_configuration' => 'Конфігурація штрих-коду',
'barcode_content' => 'Вміст штрих-коду',
'barcode_first_row' => 'Рядок 1',
'barcode_font' => 'Шрифт',
'barcode_formats' => 'Формат введення',
'barcode_generate_if_empty' => 'Створити, якщо порожньо.',
'barcode_height' => 'Висота (px)',
'barcode_id' => 'Ідентифікатор елементу/Ім\'я',
'barcode_info' => 'Інформація про конфігурацію штрих-коду',
'barcode_layout' => 'Макет штрих-коду',
'barcode_name' => 'Ім\'я',
'barcode_number' => 'Штрих-код',
'barcode_number_in_row' => 'Номер у рядку',
'barcode_page_cellspacing' => 'Відображення інтервалу клітинок на сторінці.',
'barcode_page_width' => 'Показати ширину сторінки',
'barcode_price' => 'Ціна',
'barcode_second_row' => 'Рядок 2',
'barcode_third_row' => 'Рядок 3',
'barcode_tooltip' => 'Увага! Ця функція може спричинити дублюваня елементів, імпортування або створення . Не використовуйте, якщо не хочете дублювати штрих-коди',
'barcode_type' => 'Тип штрих-коду',
'barcode_width' => 'Ширина',
'bottom' => 'Кінець',
'cash_button' => '',
'cash_button_1' => '',
'cash_button_2' => '',
'cash_button_3' => '',
'cash_button_4' => '',
'cash_button_5' => '',
'cash_button_6' => '',
'cash_decimals' => 'Десяткові суми готівки',
'cash_decimals_tooltip' => 'Якщо грошові знаки та десяткові знаки валюти однакові, то округлення готівки не відбудеться',
'cash_rounding' => 'Округлення готівки',
'category_dropdown' => 'Показати категорію як випадаюче меню',
'center' => 'Центр',
'change_apperance_tooltip' => '',
'comma' => 'Кома',
'company' => 'Назва організації',
'company_avatar' => '',
'company_change_image' => 'Змінити зображення',
'company_logo' => 'Логотип компанії',
'company_remove_image' => 'Видалити зображення',
'company_required' => 'Назва організації - обов\'язкове поле',
'company_select_image' => 'Вибрати зображення',
'company_website_url' => 'Веб-сайт організації не є дійсною URL-адресою (http: // ...)',
'country_codes' => 'Коди країн',
'country_codes_tooltip' => 'Список кодів, відокремлених комами, для пошуку номінальної адреси',
'currency_code' => 'Валютний код',
'currency_decimals' => 'Десяткові суми валюти',
'currency_symbol' => 'Символ валюти',
'current_employee_only' => '',
'customer_reward' => 'Нагорода клієнта',
'customer_reward_duplicate' => 'Нагорода з такою назвою уже існує',
'customer_reward_enable' => 'Увімкнути нагороди клієнта',
'customer_reward_invalid_chars' => 'Винагорода не може містити \'_\'',
'customer_reward_required' => 'Нагорода - обов\'язкове поле.',
'customer_sales_tax_support' => 'Податкова підтримка з продажу',
'date_or_time_format' => 'Формат дати та часу',
'datetimeformat' => 'Формат дати та часу',
'decimal_point' => 'Десяткова мітка',
'default_barcode_font_size_number' => 'Розмір шрифту штрих-коду за замовчуванням повинен бути числом',
'default_barcode_font_size_required' => 'Розмір шрифту штрих-коду за замовчуванням - обов\'язкове поле',
'default_barcode_height_number' => 'Висота штрих-коду за замовчуванням повинна бути числом',
'default_barcode_height_required' => 'Стандартна висота штрих-коду - обов\'язкове поле',
'default_barcode_num_in_row_number' => 'Номер штрих-коду за умовчанням у рядку повинен бути числом',
'default_barcode_num_in_row_required' => 'Носер штрих-коду за замовчуванням у рядку - це обов\'язкове поле',
'default_barcode_page_cellspacing_number' => 'Інтервал клітинок штрих-коду за замовчуванням повинен бути числом',
'default_barcode_page_cellspacing_required' => 'Інтервал клітинок штрих-коду за замовчуванням - це обов\'язкове поле',
'default_barcode_page_width_number' => 'Ширина сторінки штрих-коду за замовчуванням повинна бути числом',
'default_barcode_page_width_required' => 'Ширина сторінки штрих-коду за замовчуванням - це обов\'язкове поле',
'default_barcode_width_number' => 'Ширина штрих-коду за замовчуванням повинна бути числом',
'default_barcode_width_required' => 'Ширина штрих-коду за замовчуванням - це обов\'язкове поле',
'default_item_columns' => 'Стовпці видимих елементів за замовчуванням',
'default_origin_tax_code' => 'Податковий код за замовчуванням',
'default_receivings_discount' => 'Знижка на надходження за замовчуванням',
'default_receivings_discount_number' => 'Знижка надходжень за замовчуванням повинна бути числом',
'default_receivings_discount_required' => 'Знижка надходжень за замовчуванням - це обов\'язкове поле',
'default_sales_discount' => 'Знижка на продаж за замовчуванням',
'default_sales_discount_number' => 'Знижка на продаж за замовчуванням повинна бути номером',
'default_sales_discount_required' => 'Знижка з продаж за замовчуванням - обов\'язкове поле для заповнення',
'default_tax_category' => 'Податкова категорія за замовчуванням',
'default_tax_code' => 'Податковий кодекс за замовчуванням',
'default_tax_jurisdiction' => 'Податкова юрисдикція за замовчуванням',
'default_tax_name_number' => 'Назва Податку за Замовчуванням повинно бути рядком',
'default_tax_name_required' => 'Назва податку за замовчуванням - це обов\'язкове поле',
'default_tax_rate' => 'Ставка податку за замовчуванням %',
'default_tax_rate_1' => 'Ставка податку 1',
'default_tax_rate_2' => 'Ставка податку 2',
'default_tax_rate_3' => '',
'default_tax_rate_number' => 'Ставка податку за замовчуванням повинна бути числом',
'default_tax_rate_non_negative' => '',
'default_tax_rate_required' => 'Ставка податку за замовчуванням - це обов\'язкове поле',
'derive_sale_quantity' => 'Дозволити похідну кількість продажів',
'derive_sale_quantity_tooltip' => 'Якщо прапорець встановлений, то відносно товарів, замовлених на основі розширеної суми, буде передбачено новий тип товару',
'dinner_table' => 'Обідня перерва',
'dinner_table_duplicate' => 'Така назва уже існує',
'dinner_table_enable' => 'Увімкнути обідні перерви',
'dinner_table_invalid_chars' => 'Назва не може містити \'_\'',
'dinner_table_required' => 'Це поле мусить бути заповнене',
'dot' => 'Крапка',
'email' => 'Електронна пошта',
'email_configuration' => 'Конфігурація Електронної Пошти',
'email_mailpath' => 'Доступ до електронної пошта',
'email_protocol' => 'Протокол',
'email_receipt_check_behaviour' => 'Селектор «Отримати по пошті»',
'email_receipt_check_behaviour_always' => 'Завжди активний',
'email_receipt_check_behaviour_last' => 'Запам\'ятати останній вибір',
'email_receipt_check_behaviour_never' => 'Завжди деактивовано',
'email_smtp_crypto' => 'Шифрування SMTP',
'email_smtp_host' => 'SMTP Сервер',
'email_smtp_pass' => 'SMTP Пароль',
'email_smtp_pass_set' => '',
'email_smtp_port' => 'Порт SMTP',
'email_smtp_timeout' => 'Час очікування SMTP',
'email_smtp_user' => 'Ім\'я користувача SMTP',
'enable_avatar' => '',
'enable_avatar_tooltip' => '',
'enable_dropdown_tooltip' => '',
'enable_new_look' => '',
'enable_right_bar' => '',
'enable_right_bar_tooltip' => '',
'enforce_privacy' => 'Забезпечення конфіденційності',
'enforce_privacy_tooltip' => 'Захист конфіденційності даних клієнта в разі видалення даних',
'fax' => 'Факс',
'file_perm' => 'Виникають проблеми з дозволами файлів, виправте та перезавантажте сторінку.',
'financial_year' => 'Початок фінансового року',
'financial_year_apr' => '1 - е Квітня',
'financial_year_aug' => '1 - е Серпня',
'financial_year_dec' => '1 - е Грудня',
'financial_year_feb' => '1 - е Лютого',
'financial_year_jan' => '1 - е Січня',
'financial_year_jul' => '1 - е Липня',
'financial_year_jun' => '1 - е Червня',
'financial_year_mar' => '1 - е Березня',
'financial_year_may' => '1 - е Травня',
'financial_year_nov' => '1 - е Листопада',
'financial_year_oct' => '1 - е Жовтня',
'financial_year_sep' => '1 - е Вересня',
'floating_labels' => '',
'gcaptcha_enable' => 'Сторінка входу reCAPTCHA',
'gcaptcha_secret_key' => 'reCAPTCHA секретний ключ',
'gcaptcha_secret_key_required' => 'reCAPTCHA секретний ключ - це обов\'язкове поле',
'gcaptcha_site_key' => 'ключ сайту reCAPTCHA',
'gcaptcha_site_key_required' => 'Ключ сайту reCAPTCHA - це обов\'язкове поле',
'gcaptcha_tooltip' => 'Захистіть сторінку входу за допомогою Google reCAPTCHA, натисніть на піктограму для пари ключів API',
'general' => 'Загальне',
'general_configuration' => 'Загальна Конфігурація',
'giftcard_number' => 'Номер Подарункової Карти',
'giftcard_random' => 'Генерувати випадкові',
'giftcard_series' => 'Генерувати в серії',
'image_allowed_file_types' => 'Дозволені типи файлів',
'image_max_height_tooltip' => 'Максимально дозволена висота завантажуваних зображень у пікселях (px).',
'image_max_size_tooltip' => 'Максимально дозволений розмір файлу для завантаження зображень у кілобайтах.',
'image_max_width_tooltip' => 'Максимально дозволена ширина завантажуваних зображень у пікселях (px).',
'image_restrictions' => 'Обмеження на завантаження зображень',
'include_hsn' => 'Включіть підтримку кодів HSN',
'info' => 'Інформація',
'info_configuration' => 'Інформація про Магазин',
'input_groups' => '',
'integrations' => 'Інтеграції',
'integrations_configuration' => 'Інтеграція сторонніх організацій',
'invoice' => 'Рахунок-фактура',
'invoice_configuration' => 'Налаштування друку рахунків-фактур',
'invoice_default_comments' => 'Коментарі до рахунків за замовчуванням',
'invoice_email_message' => 'Шаблони рахунків-фактур на електронну пошту',
'invoice_enable' => 'Увімкнути виставлення рахунків',
'invoice_printer' => 'Друк разунку-фактура',
'invoice_type' => 'Тип рахунку-фактури',
'is_readable' => 'Читається, але дозволи встановлені неправильно. Будь ласка, встановіть доступ до файлу 640 або 660 та оновіть сторінку.',
'is_writable' => 'Можна записати, але дозволи встановлені неправильно. Будь ласка, встановіть доступ до файлу 750 та оновіть сторінку.',
'item_markup' => '',
'jsprintsetup_required' => 'Увага! Ця функція працюватиме лише у тому випадку, якщо у вас встановлений додаток FireFox jsPrintSetup. Зберегти все одно?',
'language' => 'Мова',
'last_used_invoice_number' => 'Останній використаний номер рахунку-фактури',
'last_used_quote_number' => 'Останній використаний номер котирування',
'last_used_work_order_number' => 'Останній використаний номер без виводу',
'left' => 'Залишок',
'license' => 'Ліцензія',
'license_configuration' => 'Відомості про ліцензію',
'line_sequence' => 'Послідовність рядків',
'lines_per_page' => 'Рядків на сторінці',
'lines_per_page_number' => 'Рядки на сторінці повинні бути числом',
'lines_per_page_required' => 'Рядки на сторінці - обов\'язкове поле',
'locale' => 'Визначення місцезнаходження',
'locale_configuration' => 'Місце знаходження Конфігурації',
'locale_info' => 'Інформація про Місцезнаходження Конфігурації',
'location' => 'Склад',
'location_configuration' => 'Розташування складу',
'location_info' => 'Інформація про розташування конфігурації',
'login_form' => '',
'logout' => 'Ви хочете зробити резервну копію перед виходом із системи? Натисніть [OK] для резервного копіювання або [Скасувати], щоб вийти?',
'mailchimp' => 'MailСhimp',
'mailchimp_api_key' => 'Ключ API від Mailchimp',
'mailchimp_api_key_set' => '',
'mailchimp_configuration' => 'Конфігурація Mailchimp',
'mailchimp_key_successfully' => 'Ключ API недійсний',
'mailchimp_key_unsuccessfully' => 'Ключ API невірний',
'mailchimp_lists' => 'Список(и) Mailchimp',
'mailchimp_tooltip' => 'Натисніть на піктограму для ключа API',
'message' => 'Повідомлення',
'message_configuration' => 'Конфігурація повідомлень',
'msg_msg' => 'Збережене текстове повідомлення',
'msg_msg_placeholder' => 'Якщо ви хочете використовувати шаблон SMS, збережіть своє повідомлення тут або залиште поле порожнім',
'msg_pwd' => 'Пароль SMS-API',
'msg_pwd_set' => '',
'msg_src' => 'Ідентифікатор відправника SMS-API',
'msg_src_required' => 'Ідентифікатор відправника SMS-API - обов\'язкове поле',
'msg_uid' => 'Ім\'я користувача SMS-API',
'msg_uid_required' => 'Ім\'я користувача SMS-API - обов\'язкове поле',
'multi_pack_enabled' => 'Декілька упаковок товару',
'no_risk' => 'Немає ризиків безпеки/вразливості.',
'none' => 'Жоден',
'notify_alignment' => 'Спливаюче повідомлення',
'number_format' => 'Формат номера',
'number_locale' => 'Місцезнаходження',
'number_locale_invalid' => 'Введене місцезнаходження є недійсним. Перевірте посилання в підказці, щоб знайти правильне місцезнаходження',
'number_locale_required' => 'Номер місцезнаходження - обов\'язкове поле',
'number_locale_tooltip' => 'Знайдіть відповідне місцезнаходження за цим посиланням',
'os_timezone' => 'Часова зона OSPOS:',
'ospos_info' => 'Інформація про встановлення OSPOS',
'payment_options_order' => 'Варіанти оплати замовлення',
'payment_reference_code_length_limits' => 'Код посилання на платіж<br>Обмеження довжини',
'payment_reference_code_length_max_label' => 'Макс',
'payment_reference_code_length_min_label' => 'Мін',
'perm_risk' => 'Неправильні дозволи роблять OSPOS вразливим.',
'phone' => 'Телефон організації',
'phone_required' => 'Телефон організації - обов\'язкове полею',
'print_bottom_margin' => 'Верхнє поле',
'print_bottom_margin_number' => 'Верхнє поле за замовчуванням повинно бути числом',
'print_bottom_margin_required' => 'Верхнє поле за замовчуванням - обов\'язкове поле',
'print_delay_autoreturn' => 'Затримка автоматичного повернення до продажу',
'print_delay_autoreturn_number' => 'Затримка автоматичного повернення до продажу - обов\'язкове поле',
'print_delay_autoreturn_required' => 'Затримка автоматичного повернення до продажу повинна бути числом',
'print_footer' => 'Друк веб-переглядача',
'print_header' => 'Друк заголовка браузера',
'print_left_margin' => 'Ліве поле',
'print_left_margin_number' => 'Ліве поле замовчуванням повинен бути числом',
'print_left_margin_required' => 'Ліве поле за замовчуванням - обов\'язкове поле',
'print_receipt_check_behaviour' => 'Друк квитанції, яка позначена прапорцем',
'print_receipt_check_behaviour_always' => 'Завжди перевіряється',
'print_receipt_check_behaviour_last' => 'Запам’ятати останній вибір',
'print_receipt_check_behaviour_never' => 'Ніколи не запам\'товувати',
'print_right_margin' => 'Праве поле',
'print_right_margin_number' => 'Праве поле замовчуванням за замовчуванням повинно бути числом',
'print_right_margin_required' => 'Праве поле за замовчуванням - обов\'язкове поле',
'print_silently' => 'Показати діалогове вікно друку',
'print_top_margin' => 'Верхнє поле',
'print_top_margin_number' => 'Верхнє поле за замовчуванням повинно бути числом',
'print_top_margin_required' => 'Верхнє поле за замовчуванням - обов\'язкове поле для заповнення',
'quantity_decimals' => 'Кількість десятків',
'quick_cash_enable' => '',
'quote_default_comments' => 'Кількість десятків за замовчуванням',
'receipt' => 'Квитанція',
'receipt_category' => '',
'receipt_configuration' => 'Налаштування друку квитанції',
'receipt_default' => 'За замовчуванням',
'receipt_font_size' => 'Розмір шрифту',
'receipt_font_size_number' => 'Розмір шрифту повинен бути числом',
'receipt_font_size_required' => 'Розмір шрифту - обов\'язкове поле',
'receipt_info' => 'Отримання інформації про конфігурацію',
'receipt_printer' => 'Принтер для квитків',
'receipt_short' => 'Короткий зміст',
'receipt_show_company_name' => 'Показати назву організації',
'receipt_show_description' => 'Показати опис',
'receipt_show_serialnumber' => 'Показати серійний номер',
'receipt_show_tax_ind' => 'Показати показник податку',
'receipt_show_taxes' => 'Показати податковий показник',
'receipt_show_total_discount' => 'Показати загальну знижку',
'receipt_template' => 'Шаблон квитанції',
'receiving_calculate_average_price' => 'Сер. Ціна (отримання)',
'recv_invoice_format' => 'Формат отримання рахунків-фактур',
'register_mode_default' => 'Режим реєстрації за замовчуванням',
'report_an_issue' => 'Повідомити про проблему',
'return_policy_required' => 'Політика повернення - обов\'язкове поле',
'reward' => 'Нагорода',
'reward_configuration' => 'Налаштування Нагороди',
'right' => 'Право',
'sales_invoice_format' => 'Формат рахунків-фактур продажів',
'sales_quote_format' => 'Формат котирування продажів',
'mailpath_invalid' => 'Невірний шлях sendmail. Дозволені лише літери, цифри, дефіси, підкреслення, коси риски, зворотні коси риски, двокрапки, пробіли та крапки.',
'saved_successfully' => 'Конфігурація успішно збережена',
'saved_unsuccessfully' => 'Помилка збереження конфігурації',
'security_issue' => 'Попередження про вразливість системи безпеки',
'server_notice' => 'Будь ласка, використовуйте інформацію подану нижче для звіту про проблеми',
'service_charge' => '',
'show_due_enable' => '',
'show_office_group' => 'Показати значок офісу',
'statistics' => 'Надіслати статистику',
'statistics_tooltip' => 'Надсилайте статистику для розробки та вдосконалення функцій',
'stock_location' => 'Місцезнаходження складу',
'stock_location_default' => 'Типове місцезнаходження складу',
'stock_location_default_header' => 'Типово',
'stock_location_duplicate' => 'Склад з таким місцезнаходженням вже існує. Будь ласка, використайте інше',
'stock_location_invalid_chars' => 'Місцезнаходження не може містити спецсимволів',
'stock_location_name_header' => 'Назва',
'stock_location_required' => 'Місцезнаходження - обов\'язкове поле',
'suggestions_fifth_column' => '',
'suggestions_first_column' => 'Колонка 1',
'suggestions_fourth_column' => '',
'suggestions_layout' => 'Формат пошукових пропозицій',
'suggestions_second_column' => 'Колонка 2',
'suggestions_third_column' => 'Колонка 3',
'shortcuts' => '',
'shortcuts_configuration' => '',
'shortcuts_duplicate_bindings' => '',
'shortcuts_save_error' => '',
'system_conf' => 'Налаштування',
'system_info' => 'Інформація про систему',
'system_info_copy' => '',
'system_info_copy_error' => '',
'system_info_copy_success' => '',
'table' => 'Таблиця',
'table_configuration' => 'Налаштування таблиці',
'takings_printer' => 'Підключення принтера',
'tax' => 'Податок',
'tax_category' => 'Категорія податку',
'tax_category_duplicate' => 'Введена податкова категорія вже існує',
'tax_category_invalid_chars' => 'Введена категорія податку недійсна',
'tax_category_required' => 'Податкова категорія - обов\'язкове поле',
'tax_category_used' => 'Податкову категорію не можливо видалити, оскільки вона використовується',
'tax_configuration' => 'Налаштування податку.',
'tax_decimals' => 'Податкові десятки',
'tax_id' => 'Податковий номер',
'tax_included' => 'Податок включений',
'theme' => 'Тема',
'theme_preview' => '',
'thousands_separator' => 'Роздільник тисячних розрядів',
'timezone' => 'Часовой пояс',
'timezone_error' => 'Часовий пояс OSPOS відрізняється від вашого місцевого часового поясу.',
'top' => 'Головний',
'use_destination_based_tax' => 'Використовуйте податок на основі призначення',
'user_timezone' => 'Місцевий часовий пояс:',
'website' => 'Веб-сайт',
'wholesale_markup' => '',
'work_order_enable' => 'Підтримка робочого замовлення',
'work_order_format' => 'Формат робочого замовлення',
];