159 Commits

Author SHA1 Message Date
mchev
83caff13cd Merge pull request #615 from InvoiceShelf/translations
New Crowdin updates
2026-04-08 09:29:39 +02:00
mchev
d2736b1c46 Merge pull request #616 from mchev/taxdecimal
Support 3-decimal tax percentages (e.g. 6.625%)
2026-04-08 09:28:44 +02:00
mchev
cdc504f518 Merge pull request #617 from mchev/duplicate_expense
Add duplicate expense action
2026-04-08 09:28:22 +02:00
Darko Gjorgjijoski
2c840b2d97 Bump version from 2.3.2 to 2.3.3 2026-04-07 21:25:20 +02:00
Darko Gjorgjijoski
34db4b7897 Sanitize PDF address fields against SSRF, not just notes
Closes the residual surface from the three published SSRF advisories (GHSA-pc5v-8xwc-v9xq, GHSA-38hf-fq8x-q49r, GHSA-q9wx-ggwq-mcgh / CVE-2026-34365 to 34367). The original fix in 07757e74 only sanitized the Notes field via Invoice/Estimate/Payment::getNotes(), but the same blade templates also render company/billing/shipping address fields with {!! !!} (Blade unescaped output). Those address strings are produced by getCompanyAddress(), getCustomerBillingAddress(), getCustomerShippingAddress() which feed into GeneratesPdfTrait::getFormattedString() — and that method does not call PdfHtmlSanitizer.

Customer-controlled fields (name, street, phone, custom field values) are substituted into address templates via getFieldsArray() without HTML-escaping. A malicious customer name like "Acme <img src='http://attacker/probe'>" therefore reaches Dompdf as raw HTML through the address path, exactly the same CWE-918 SSRF pattern the advisories describe — only blocked today by the secondary defense of dompdf's enable_remote=false. If a self-hoster sets DOMPDF_ENABLE_REMOTE=true for legitimate remote logos, the address surface immediately re-opens.

Move the PdfHtmlSanitizer::sanitize() call into the chokepoint at GeneratesPdfTrait::getFormattedString(), so all four sinks — notes plus the three address fields, on all three models — get the same treatment via a single call site. The explicit wrapper in each model's getNotes() becomes redundant and is removed (along with the now-unused App\Support\PdfHtmlSanitizer imports). Verified getFormattedString() is only called from PDF code paths (no email body callers, which use strtr() directly) so there is no risk of stripping useful HTML from a non-PDF context.

Extends tests/Unit/PdfHtmlSanitizerTest.php with three new cases covering the address-template scenario, iframe/link tag stripping, and on* event handler removal. All 8 tests pass via vendor/bin/pest tests/Unit/PdfHtmlSanitizerTest.php.
2026-04-07 20:39:19 +02:00
mchev
beb2a43ed3 Duplicate expense 2026-04-07 19:00:07 +02:00
mchev
7a25a15877 Increasing tax decimal 2026-04-07 18:35:30 +02:00
Darko Gjorgjijoski
8eee4bc4f5 New translations en.json (Serbian (Latin)) 2026-04-07 14:51:02 +02:00
Darko Gjorgjijoski
c34cfeea11 New translations en.json (Swahili) 2026-04-07 14:51:01 +02:00
Darko Gjorgjijoski
f37edbcc92 New translations en.json (Malay) 2026-04-07 14:50:59 +02:00
Darko Gjorgjijoski
ba581313df New translations en.json (Hindi) 2026-04-07 14:50:58 +02:00
Darko Gjorgjijoski
1c1a180dd5 New translations en.json (Latvian) 2026-04-07 14:50:57 +02:00
Darko Gjorgjijoski
8e815fd887 New translations en.json (Estonian) 2026-04-07 14:50:56 +02:00
Darko Gjorgjijoski
df612bc773 New translations en.json (Croatian) 2026-04-07 14:50:55 +02:00
Darko Gjorgjijoski
10b2cf5af1 New translations en.json (Thai) 2026-04-07 14:50:53 +02:00
Darko Gjorgjijoski
f140256efd New translations en.json (Bengali) 2026-04-07 14:50:52 +02:00
Darko Gjorgjijoski
1ed8e5b2d0 New translations en.json (Persian) 2026-04-07 14:50:50 +02:00
Darko Gjorgjijoski
fcb7c96bca New translations en.json (Indonesian) 2026-04-07 14:50:49 +02:00
Darko Gjorgjijoski
d587e3fd00 New translations en.json (Portuguese, Brazilian) 2026-04-07 14:50:48 +02:00
Darko Gjorgjijoski
1b26d47539 New translations en.json (Vietnamese) 2026-04-07 14:50:47 +02:00
Darko Gjorgjijoski
340522da19 New translations en.json (Urdu (Pakistan)) 2026-04-07 14:50:45 +02:00
Darko Gjorgjijoski
3ecfcede3e New translations en.json (Chinese Traditional) 2026-04-07 14:50:44 +02:00
Darko Gjorgjijoski
30f76c044a New translations en.json (Chinese Simplified) 2026-04-07 14:50:43 +02:00
Darko Gjorgjijoski
854a8bb50d New translations en.json (Ukrainian) 2026-04-07 14:50:41 +02:00
Darko Gjorgjijoski
1be3132dc4 New translations en.json (Turkish) 2026-04-07 14:50:40 +02:00
Darko Gjorgjijoski
fefd856cfb New translations en.json (Swedish) 2026-04-07 14:50:39 +02:00
Darko Gjorgjijoski
e5fe62e4de New translations en.json (Albanian) 2026-04-07 14:50:38 +02:00
Darko Gjorgjijoski
129d63c5b1 New translations en.json (Slovenian) 2026-04-07 14:50:37 +02:00
Darko Gjorgjijoski
65e9182272 New translations en.json (Slovak) 2026-04-07 14:50:35 +02:00
Darko Gjorgjijoski
3abcba2752 New translations en.json (Russian) 2026-04-07 14:50:34 +02:00
Darko Gjorgjijoski
6c1e51d126 New translations en.json (Portuguese) 2026-04-07 14:50:33 +02:00
Darko Gjorgjijoski
c1b8ba448d New translations en.json (Polish) 2026-04-07 14:50:31 +02:00
Darko Gjorgjijoski
ab5ea81424 New translations en.json (Norwegian) 2026-04-07 14:50:30 +02:00
Darko Gjorgjijoski
befd69fdb2 New translations en.json (Dutch) 2026-04-07 14:50:29 +02:00
Darko Gjorgjijoski
417b92ad9f New translations en.json (Macedonian) 2026-04-07 14:50:27 +02:00
Darko Gjorgjijoski
d6b1e102fe New translations en.json (Lithuanian) 2026-04-07 14:50:26 +02:00
Darko Gjorgjijoski
d7bf942da2 New translations en.json (Georgian) 2026-04-07 14:50:25 +02:00
Darko Gjorgjijoski
5db82db958 New translations en.json (Japanese) 2026-04-07 14:50:24 +02:00
Darko Gjorgjijoski
c63355391a New translations en.json (Italian) 2026-04-07 14:50:22 +02:00
Darko Gjorgjijoski
de3c8f89fb New translations en.json (Hungarian) 2026-04-07 14:50:21 +02:00
Darko Gjorgjijoski
cab4c62c5d New translations en.json (Hebrew) 2026-04-07 14:50:20 +02:00
Darko Gjorgjijoski
4b634f96c9 New translations en.json (Finnish) 2026-04-07 14:50:19 +02:00
Darko Gjorgjijoski
9ef0932c6e New translations en.json (Greek) 2026-04-07 14:50:17 +02:00
Darko Gjorgjijoski
d122c8c95a New translations en.json (German) 2026-04-07 14:50:16 +02:00
Darko Gjorgjijoski
820073e8e0 New translations en.json (Danish) 2026-04-07 14:50:14 +02:00
Darko Gjorgjijoski
80c14b4b7f New translations en.json (Czech) 2026-04-07 14:50:13 +02:00
Darko Gjorgjijoski
174acbf70e New translations en.json (Catalan) 2026-04-07 14:50:12 +02:00
Darko Gjorgjijoski
c93b8f0da9 New translations en.json (Bulgarian) 2026-04-07 14:50:11 +02:00
Darko Gjorgjijoski
2693b0b0f2 New translations en.json (Arabic) 2026-04-07 14:50:09 +02:00
Darko Gjorgjijoski
54d9c57925 New translations en.json (Spanish) 2026-04-07 14:50:08 +02:00
Darko Gjorgjijoski
ba3e94c4ad New translations en.json (French) 2026-04-07 14:50:07 +02:00
Darko Gjorgjijoski
a644653513 New translations en.json (Romanian) 2026-04-07 14:50:05 +02:00
Darko Gjorgjijoski
3391d104f9 Update source file en.json 2026-04-07 14:50:00 +02:00
mchev
f17c7be5f0 Merge pull request #611 from klittle81/EnhanceExpenseReport
Enhance Expense Report - Grouped itemized Expenses By Expense Category
2026-04-07 12:58:09 +02:00
mchev
0e9f18d4d1 fix: i18n for expense report PDF and correct report controller return types
Add expenses.uncategorized and pdf_expense_group_total_label; use the new key
in the grouped expense template; document View|Response instead of JsonResponse.

Made-with: Cursor
2026-04-07 10:43:02 +02:00
mchev
e22050bc71 fix: use DomPDF Pdf facade and Pint style in expense report
Replace legacy PDF facade alias with Barryvdh\DomPDF\Facade\Pdf so CI Pint passes.

Made-with: Cursor
2026-04-07 10:31:48 +02:00
mchev
af9d672574 Bump version from 2.3.1 to 2.3.2 2026-04-06 11:02:23 +02:00
mchev
7606f8ece8 Merge pull request #585 from InvoiceShelf/translations
New Crowdin updates
2026-04-06 11:00:58 +02:00
mchev
9b0498a2e5 Merge pull request #583 from sirlupusdev/fix-setup-wizard
Fix: Set Slug when creating/updating first company
2026-04-06 10:54:57 +02:00
mchev
04c7682e73 Merge pull request #584 from sirlupusdev/feat-auto-due-date
Feat: Automatically set due date when invoice date is changed
2026-04-06 10:50:05 +02:00
Darko Gjorgjijoski
88650c2f3e Bump version 2026-04-05 12:34:24 +02:00
Darko Gjorgjijoski
ee76f31138 Add log mail driver support to frontend
The default mail driver in config/mail.php is 'log', which had no
matching Vue component, causing the mail configuration step in the
install wizard (and settings page) to render empty.
2026-04-05 12:33:14 +02:00
Darko Gjorgjijoski
e1af9f56c4 Docker optimizations 2026-04-05 12:07:47 +02:00
mchev
fdd860c381 Merge pull request #612 from mchev/master
Ensure public/storage symlink exists in Docker production entrypoint
2026-04-04 18:57:09 +02:00
klittle81
834b53ea40 Enhance Expense Report - Grouped itemized expenses 2026-04-04 11:22:32 -04:00
Darko Gjorgjijoski
5ff051fbb5 Bump version from 2.2.1 to 2.3.0 2026-04-04 17:12:13 +02:00
Darko Gjorgjijoski
0d7059fcf6 Fix logout/re-login CSRF mismatch and stale token issues
Cherry-picked from v3.0 branch. Three fixes:
1. Refresh CSRF cookie after logout (auth.js)
2. Clear auth.token and selectedCompany from localStorage on logout (auth.js)
3. Invalidate session and regenerate CSRF token on server-side logout (web.php)

Without these, logging out and back in as a different user would fail
with CSRF token mismatch and 401 Unauthenticated errors because the
browser held stale session cookies and localStorage tokens.
2026-04-03 23:53:56 +02:00
Darko Gjorgjijoski
7d9fdb79cc Scope users listing and search to current company (#607)
Add scopeWhereCompany() to User model using whereHas through the
user_company pivot table. Apply it in UsersController::index() and
SearchController so users only see members of their current company.

Previously, the users page showed ALL users across all companies.

Ref #574
2026-04-03 14:34:33 +02:00
Darko Gjorgjijoski
3d871604ae Add company ownership check to clone endpoints (#606)
Verify the source record belongs to the current company before cloning.
Previously, users could clone invoices/estimates from other companies,
leaking sensitive data (amounts, customer details, items, taxes, notes).

The view policy already includes hasCompany() check, so authorizing
view on the source record gates both ability and company ownership.

Ref #574
2026-04-03 14:32:12 +02:00
Darko Gjorgjijoski
1adebe85b9 Scope all bulk deletes to current company and fix inverted ownership transfer (#605)
Bulk delete: filter IDs through whereCompany() before deleting in all
controllers (Invoices, Payments, Items, Expenses, Estimates, Recurring
Invoices). Previously, any user could delete records from other companies
by providing cross-company IDs.

Transfer ownership: fix inverted hasCompany() check that allowed
transferring company ownership to users who do NOT belong to the company,
while blocking users who DO belong.

Ref #567
2026-04-03 14:16:42 +02:00
Darko Gjorgjijoski
defbfc6406 Fix CustomerPolicy missing hasCompany() check (IDOR) (#604)
* Fix CustomerPolicy missing hasCompany() check (cross-company IDOR)

Add $user->hasCompany($customer->company_id) check to view, update,
delete, restore, and forceDelete methods in CustomerPolicy, matching
the pattern used by all other policies (InvoicePolicy, PaymentPolicy,
EstimatePolicy, etc.).

Without this check, a user in Company A with view-customer ability
could access customers belonging to Company B by providing the target
customer's ID.

Add cross-company authorization tests to verify the fix.

Closes #565

* Scope bulk delete to current company to prevent cross-company deletion

Filter customer IDs through whereCompany() before passing to
deleteCustomers(), ensuring users cannot delete customers belonging
to other companies via the bulk delete endpoint.
2026-04-03 13:56:34 +02:00
Darko Gjorgjijoski
25986b7bd5 Update IDE helpers, Tailwind skill to v4, and refresh dependencies 2026-04-02 21:03:55 +02:00
Darko Gjorgjijoski
751bd4a1c8 Upgrade ChartJS from v2 to v4 (#603) 2026-04-02 20:02:49 +02:00
Darko Gjorgjijoski
0e313b80ca Upgrade @vueuse/core from v12 to v14 (#602) 2026-04-02 18:09:43 +02:00
Darko Gjorgjijoski
5014a75fbc Upgrade eslint tooling to v10 and fix linting bugs (#601)
- Upgrade eslint 9→10, eslint-config-prettier 9→10, eslint-plugin-vue 9→10
- Upgrade @types/node 20→24
- Migrate from legacy .eslintrc.mjs to flat config eslint.config.mjs
- Remove --ext flag from npm test script (dropped in eslint 10)
- Fix vue/no-ref-as-operand: add missing .value to ref assignments (5 files)
- Fix vue/return-in-computed-property: add default returns (2 files)
- Fix vue/no-side-effects-in-computed-properties: move mutation to watcher
- Fix vue/no-dupe-keys: remove ref shadowing prop in DomPDFDriver
- Fix vue/no-deprecated-slot-attribute: migrate to v-slot syntax (3 files)
- Fix vue/require-valid-default-prop: use factory function for array default
- Fix vue/no-unused-vars: remove unused slot destructure
- Disable vue/no-mutating-props (false positive for Pinia store props)
2026-04-02 17:33:18 +02:00
Darko Gjorgjijoski
9e5b9fdaad Upgrade vue-flatpickr-component from v11 to v12 (#600) 2026-04-02 17:17:17 +02:00
Darko Gjorgjijoski
08dfe62312 Standardize Node.js version to 24 (#599)
Update Node.js from 20 to 24 across CI workflows, Dockerfiles,
package.json engines field, and add .node-version file for consistent
local development.
2026-04-02 17:08:39 +02:00
Darko Gjorgjijoski
f623cd0179 Upgrade vue-router from v4 to v5 (#598)
- Migrate beforeEach navigation guard from next() callback to return-based
  API, preparing for vue-router v6 where next() is removed
2026-04-02 16:47:16 +02:00
mchev
77fd96d499 Merge branch 'master' of https://github.com/mchev/InvoiceShelf 2026-04-02 16:43:57 +02:00
mchev
2e4e19dfc5 Remove testing image 2026-04-02 16:43:22 +02:00
mchev
76c02be219 Merge branch 'InvoiceShelf:master' into master 2026-04-02 16:42:13 +02:00
Darko Gjorgjijoski
414531524c Remove unused cross-env dependency 2026-04-02 16:39:10 +02:00
Darko Gjorgjijoski
d75a957183 Upgrade Tiptap from v2 to v3 (#597)
- Upgrade @tiptap/core, starter-kit, vue-3, pm, extension-text-align to v3
- Remove @tiptap/extension-link (now bundled in StarterKit v3)
- Move Link config into StarterKit.configure()
2026-04-02 16:35:43 +02:00
Darko Gjorgjijoski
63d3a7fc8e Skip PHP CI jobs when only non-PHP files change
Replace workflow-level paths-ignore with per-job filtering using
dorny/paths-filter. PHP lint and test jobs now only run when PHP-related
files (app/, config/, database/, routes/, tests/, composer.*, phpunit.xml)
are modified.
2026-04-02 16:35:07 +02:00
Darko Gjorgjijoski
0be747a483 Pin axios to 1.14.0
Avoid possible supply chain attacks in future caused by compromised
author account or even rogue author.
2026-04-02 16:14:47 +02:00
Darko Gjorgjijoski
3ceb08bc31 Upgrade Pinia from v2 to v3 (#596)
Migrate all 37 store definitions from the deprecated object-with-id
signature to the string-id-first signature required by Pinia 3:

  defineStore({ id: 'name', ... }) → defineStore('name', { ... })
2026-04-02 16:12:11 +02:00
Darko Gjorgjijoski
ad5a7e51b9 Upgrade to Vite 8 and Tailwind CSS 4 (#595)
- Vite 6 → 8 (Rolldown bundler), laravel-vite-plugin 1 → 3, @vitejs/plugin-vue 5 → 6
- Tailwind CSS 3 → 4 with CSS-based config (@theme, @plugin, @utility)
- Add @tailwindcss/vite plugin, remove postcss/autoprefixer/sass
- Convert SCSS files to plain CSS (resources/sass → resources/css)
- Migrate tailwind.config.js to CSS @theme directives
- Rename deprecated utility classes (shadow-sm→shadow-xs, outline-none→outline-hidden,
  rounded-sm→rounded-xs, bg-gradient-to→bg-linear-to, ring→ring-3)
- Migrate opacity utilities to color modifiers (bg-opacity, text-opacity,
  border-opacity, ring-opacity → color/N syntax)
- Update primary color CSS vars to full rgb() values for TW4 color-mix()
- Fix border-l color specificity for sidebar navigation (TW4 default border
  color changed from gray-200 to currentColor)
- Fix invalid border color classes (border-grey-light, border-modal-bg, border--200)
- Add @reference directive for @apply in Vue component style blocks
- Convert Vue component <style lang="scss"> blocks to plain CSS
2026-04-02 15:59:15 +02:00
Darko Gjorgjijoski
691178857f Add HTTP client wrapper and upgrade Axios to v1 (#594)
* refactor: add HTTP client wrapper and upgrade axios to v1

Introduce a thin HTTP wrapper (resources/scripts/http) that centralizes
axios configuration, interceptors, and auth header injection. All 43
files now import from the wrapper instead of axios directly, making
future library swaps a single-file change. Upgrade axios from 0.30.0
to 1.14.0.

* fix: restore window.Ls assignment removed during axios refactor

company.js uses window.Ls.set() to persist selected company,
which broke after the axios plugin (that set window.Ls) was deleted.
2026-04-02 15:08:23 +02:00
Darko Gjorgjijoski
a38f09cf7b Installer reliability improvements (#593)
* docs: add CLAUDE.md for Claude Code guidance

* fix: handle missing settings table in installation middlewares

RedirectIfInstalled crashed with "no such table: settings" when the
database_created marker file existed but the database was empty.
Changed to use isDbCreated() which verifies actual tables, and added
try-catch around Setting queries in both middlewares.

* feat: pre-select database driver from env in installation wizard

The database step now reads DB_CONNECTION from the environment and
pre-selects the matching driver on load, including correct defaults
for hostname and port.

* feat: pre-select mail driver and config from env in installation wizard

The email step now fetches the current mail configuration on load
instead of hardcoding the driver to 'mail'. SMTP fields fall back
to Laravel config values from the environment.

* refactor: remove file-based DB marker in favor of direct DB checks

The database_created marker file was a second source of truth that
could drift out of sync with the actual database. InstallUtils now
checks the database directly via Schema::hasTable which is cached
per-request and handles all error cases gracefully.
2026-04-02 14:48:08 +02:00
mchev
de4ba6bba0 Fix storage link on docker 2026-04-02 11:56:16 +02:00
mchev
375cfc6b18 Merge pull request #591 from mchev/588
Fix PDF notes line breaks
2026-04-01 21:38:14 +02:00
mchev
aa88dc340d Closes #588 2026-04-01 21:30:32 +02:00
mchev
7004bf375e Merge pull request #587 from rihards-simanovics/rihards-simanovics/issue586
Fix docker containers failing to create SQL backups due to missing OS dependencies
2026-03-27 08:15:43 +01:00
mchev
80889293bf Merge pull request #508 from alexdev01012020/email-backup
Overrite the email notification for backup
2026-03-27 08:04:02 +01:00
Rihards Simanovics
d754c4d29e fix: return missing development docker sql dependencies
Fixes #586
2026-03-27 00:18:15 +00:00
Rihards Simanovics
8de32e27d3 fix: return missing production docker sql dependencies
Fixes #586
2026-03-27 00:17:56 +00:00
Darko Gjorgjijoski
0f933b6217 New translations en.json (Hindi) 2026-03-26 19:47:36 +01:00
mchev
3bae2c282c Merge pull request #576 from csalzano/fix/remote-disk-backup-listing
Fix remote disk backups never appear in backup listing
2026-03-26 09:16:13 +01:00
Corey Salzano
14b5aaa0c9 Runs pint 2026-03-25 09:09:33 -04:00
lupus0802
241ec09220 Feat: Automatically set due date when invoice date is changed 2026-03-25 13:06:39 +01:00
lupus0802
ed7af3fc3c Fix: Set Slug when creating/updating first company 2026-03-25 13:05:23 +01:00
Corey Salzano
aafcf147cf Updates the "create backup" test to handle the disk prefix. 2026-03-24 23:00:47 -04:00
mchev
7e8f9e65fb Merge pull request #580 from InvoiceShelf/translations
New Crowdin updates
2026-03-24 12:27:36 +01:00
mchev
67739750ca Merge pull request #582 from mchev/master
Hot fix  #280
2026-03-24 12:26:27 +01:00
mchev
5f6a7b92bf Merge pull request #581 from swiffer/master
Import File facade in UpdateCommand
2026-03-24 12:26:00 +01:00
mchev
ff3cab570a Hot fix #280 2026-03-24 12:13:40 +01:00
Darko Gjorgjijoski
11024ddc38 Update source file en.json 2026-03-24 09:30:45 +01:00
Matthias Wirtz
71303a1050 Import File facade in UpdateCommand
Added use statement for File facade.
2026-03-24 08:03:53 +01:00
Darko Gjorgjijoski
3af0e83d26 New translations en.json (Serbian (Latin)) 2026-03-24 07:44:53 +01:00
Darko Gjorgjijoski
a866a26e9f New translations en.json (Swahili) 2026-03-24 07:44:52 +01:00
Darko Gjorgjijoski
154a4dc076 New translations en.json (Malay) 2026-03-24 07:44:51 +01:00
Darko Gjorgjijoski
7900e020f5 New translations en.json (Hindi) 2026-03-24 07:44:50 +01:00
Darko Gjorgjijoski
974efb36da New translations en.json (Latvian) 2026-03-24 07:44:49 +01:00
Darko Gjorgjijoski
45d84b8b3c New translations en.json (Estonian) 2026-03-24 07:44:48 +01:00
Darko Gjorgjijoski
fdfb46ed79 New translations en.json (Croatian) 2026-03-24 07:44:46 +01:00
Darko Gjorgjijoski
ddcef0fb2c New translations en.json (Thai) 2026-03-24 07:44:45 +01:00
Darko Gjorgjijoski
0254b16556 New translations en.json (Bengali) 2026-03-24 07:44:44 +01:00
Darko Gjorgjijoski
a9a52ca85f New translations en.json (Persian) 2026-03-24 07:44:43 +01:00
Darko Gjorgjijoski
708d880b52 New translations en.json (Indonesian) 2026-03-24 07:44:42 +01:00
Darko Gjorgjijoski
57406989d4 New translations en.json (Portuguese, Brazilian) 2026-03-24 07:44:41 +01:00
Darko Gjorgjijoski
5d7e46b026 New translations en.json (Vietnamese) 2026-03-24 07:44:39 +01:00
Darko Gjorgjijoski
8e034e59f8 New translations en.json (Urdu (Pakistan)) 2026-03-24 07:44:38 +01:00
Darko Gjorgjijoski
43951d4542 New translations en.json (Chinese Traditional) 2026-03-24 07:44:37 +01:00
Darko Gjorgjijoski
3cc0f41d8c New translations en.json (Chinese Simplified) 2026-03-24 07:44:36 +01:00
Darko Gjorgjijoski
5f34ae558c New translations en.json (Ukrainian) 2026-03-24 07:44:35 +01:00
Darko Gjorgjijoski
70d51d580d New translations en.json (Turkish) 2026-03-24 07:44:34 +01:00
Darko Gjorgjijoski
b7929672fb New translations en.json (Swedish) 2026-03-24 07:44:32 +01:00
Darko Gjorgjijoski
bd28849a9f New translations en.json (Albanian) 2026-03-24 07:44:31 +01:00
Darko Gjorgjijoski
4d21aadcd4 New translations en.json (Slovenian) 2026-03-24 07:44:30 +01:00
Darko Gjorgjijoski
373a824fdb New translations en.json (Slovak) 2026-03-24 07:44:29 +01:00
Darko Gjorgjijoski
a5d9a60d5c New translations en.json (Russian) 2026-03-24 07:44:28 +01:00
Darko Gjorgjijoski
2537b53506 New translations en.json (Portuguese) 2026-03-24 07:44:27 +01:00
Darko Gjorgjijoski
bbc2d2088a New translations en.json (Polish) 2026-03-24 07:44:25 +01:00
Darko Gjorgjijoski
5734a06ab3 New translations en.json (Norwegian) 2026-03-24 07:44:24 +01:00
Darko Gjorgjijoski
75a1038245 New translations en.json (Dutch) 2026-03-24 07:44:23 +01:00
Darko Gjorgjijoski
017691b7b1 New translations en.json (Macedonian) 2026-03-24 07:44:22 +01:00
Darko Gjorgjijoski
d4f8a40982 New translations en.json (Lithuanian) 2026-03-24 07:44:21 +01:00
Darko Gjorgjijoski
ebdee1e3f0 New translations en.json (Georgian) 2026-03-24 07:44:20 +01:00
Darko Gjorgjijoski
ce97a474f9 New translations en.json (Japanese) 2026-03-24 07:44:18 +01:00
Darko Gjorgjijoski
4ee3d0d129 New translations en.json (Italian) 2026-03-24 07:44:17 +01:00
Darko Gjorgjijoski
bd5abdec0e New translations en.json (Hungarian) 2026-03-24 07:44:16 +01:00
Darko Gjorgjijoski
995533974e New translations en.json (Hebrew) 2026-03-24 07:44:15 +01:00
Darko Gjorgjijoski
156e94f931 New translations en.json (Finnish) 2026-03-24 07:44:14 +01:00
Darko Gjorgjijoski
e38c4963ef New translations en.json (Greek) 2026-03-24 07:44:13 +01:00
Darko Gjorgjijoski
d7efbb5c47 New translations en.json (German) 2026-03-24 07:44:11 +01:00
Darko Gjorgjijoski
3cd219e7b3 New translations en.json (Danish) 2026-03-24 07:44:10 +01:00
Darko Gjorgjijoski
3d65a09038 New translations en.json (Czech) 2026-03-24 07:44:09 +01:00
Darko Gjorgjijoski
f52c376a49 New translations en.json (Catalan) 2026-03-24 07:44:08 +01:00
Darko Gjorgjijoski
5a7c1363ee New translations en.json (Bulgarian) 2026-03-24 07:44:07 +01:00
Darko Gjorgjijoski
2c40c2ef06 New translations en.json (Arabic) 2026-03-24 07:44:06 +01:00
Darko Gjorgjijoski
b5ff16c318 New translations en.json (Spanish) 2026-03-24 07:44:04 +01:00
Darko Gjorgjijoski
4d7b818d23 New translations en.json (French) 2026-03-24 07:44:03 +01:00
Darko Gjorgjijoski
b314ebc07f New translations en.json (Romanian) 2026-03-24 07:44:02 +01:00
mchev
254ed5ade0 Merge pull request #579 from mchev/upgrade_requirements
PHP8.4 requirement
2026-03-24 07:15:33 +01:00
mchev
40e4ea931e PHP8.4 requirement 2026-03-24 07:07:41 +01:00
Corey Salzano
3c31baf20d fix(backup): remote disk backups never appear in backup listing
Three bugs prevented backups stored on remote disks (Dropbox, S3, etc.)
from ever appearing in the Settings > Backup listing:

1. Typo in BackupSetting.vue: `filed_disk_id` was sent to the API
   instead of `file_disk_id`, so the backend never received the selected
   disk ID and always fell back to the local filesystem.

2. Wrong default disk selection in loadDisksData(): `set_as_default == 0`
   selected the first disk that is NOT default (local_public), instead of
   the disk that IS default. Changed to `set_as_default == 1` with a
   fallback to the first disk.

3. BackupsController::index() did not call setConfig() on the FileDisk
   before querying backups, so even when the correct file_disk_id arrived
   it still read from the default local filesystem. Added the same disk
   bootstrap logic already present in CreateBackupJob and destroy().

Made-with: Cursor
2026-03-17 19:32:40 -04:00
Alex
a386fd19fc Merge remote-tracking branch 'upstream/master' into email-backup 2026-02-15 12:37:13 +02:00
Alex
e5f6984078 Apply review feedback 2026-02-06 16:17:57 +02:00
Alex
d2953e9409 Overrite the email notification for backup 2025-11-05 19:14:55 +02:00
260 changed files with 18386 additions and 10118 deletions

View File

@@ -10,7 +10,7 @@ metadata:
## Documentation
Use `search-docs` for detailed Tailwind CSS v3 patterns and documentation.
Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation.
## Basic Usage
@@ -18,22 +18,55 @@ Use `search-docs` for detailed Tailwind CSS v3 patterns and documentation.
- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue).
- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically.
## Tailwind CSS v3 Specifics
## Tailwind CSS v4 Specifics
- Always use Tailwind CSS v3 and verify you're using only classes it supports.
- Configuration is done in the `tailwind.config.js` file.
- Import using `@tailwind` directives:
- Always use Tailwind CSS v4 and avoid deprecated utilities.
- `corePlugins` is not supported in Tailwind v4.
<!-- v3 Import Syntax -->
### CSS-First Configuration
In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed:
<!-- CSS-First Config -->
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
@theme {
--color-brand: oklch(0.72 0.11 178);
}
```
### Import Syntax
In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3:
<!-- v4 Import Syntax -->
```diff
- @tailwind base;
- @tailwind components;
- @tailwind utilities;
+ @import "tailwindcss";
```
### Replaced Utilities
Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain numeric.
| Deprecated | Replacement |
|------------|-------------|
| bg-opacity-* | bg-black/* |
| text-opacity-* | text-black/* |
| border-opacity-* | border-black/* |
| divide-opacity-* | divide-black/* |
| ring-opacity-* | ring-black/* |
| placeholder-opacity-* | placeholder-black/* |
| flex-shrink-* | shrink-* |
| flex-grow-* | grow-* |
| overflow-ellipsis | text-ellipsis |
| decoration-slice | box-decoration-slice |
| decoration-clone | box-decoration-clone |
## Spacing
When listing items, use gap utilities for spacing; don't use margins.
Use `gap` utilities instead of margins for spacing between siblings:
<!-- Gap Utilities -->
```html
@@ -77,15 +110,10 @@ If existing pages and components support dark mode, new pages and components mus
</div>
```
## Verification
1. Check browser for visual rendering
2. Test responsive breakpoints
3. Verify dark mode if project uses it
## Common Pitfalls
- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.)
- Using `@tailwind` directives instead of `@import "tailwindcss"`
- Trying to use `tailwind.config.js` instead of CSS `@theme` directive
- Using margins for spacing between siblings instead of gap utilities
- Forgetting to add dark mode variants when the project uses dark mode
- Not checking existing project conventions before adding new utilities
- Overusing inline styles when Tailwind classes would suffice
- Forgetting to add dark mode variants when the project uses dark mode

View File

@@ -1,14 +0,0 @@
// .eslintrc.js
module.exports = {
extends: [
// add more generic rulesets here, such as:
// 'eslint:recommended',
"plugin:vue/vue3-recommended",
"prettier",
],
rules: {
// override/add rules settings here, such as:
// 'vue/no-unused-vars': 'error'
},
};

View File

@@ -3,28 +3,41 @@ name: Check
# Run this workflow every time a new commit pushed to your repository
on:
push:
paths-ignore:
- '.github/**/*'
- '**/*.md'
- 'public/build/*.js'
- 'public/build/**/*.js'
- 'docker/**/*'
- 'resources/scripts/**/*'
tags-ignore:
- "*"
branches-ignore:
- 'translations'
pull_request:
paths-ignore:
- '**/*.md'
- 'public/build/*.js'
- 'public/build/**/*.js'
branches-ignore:
- 'translations'
# Allow manually triggering the workflow.
workflow_dispatch:
jobs:
changes:
name: 🔍 Detect changes
runs-on: ubuntu-latest
outputs:
php: ${{ steps.filter.outputs.php }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check for file changes
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
php:
- 'app/**'
- 'config/**'
- 'database/**'
- 'routes/**'
- 'tests/**'
- 'composer.json'
- 'composer.lock'
- 'phpunit.xml'
kill_previous:
name: 0⃣ Kill previous runs
runs-on: ubuntu-latest
@@ -41,6 +54,8 @@ jobs:
runs-on: ubuntu-latest
needs:
- kill_previous
- changes
if: needs.changes.outputs.php == 'true'
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
@@ -60,6 +75,8 @@ jobs:
name: 2⃣ PHP ${{ matrix.php-version }} Tests
needs:
- php_syntax_errors
- changes
if: needs.changes.outputs.php == 'true'
runs-on: ubuntu-latest
strategy:
matrix:
@@ -83,10 +100,10 @@ jobs:
- name: Install Composer dependencies
uses: ramsey/composer-install@v2
- name: Use Node.js 20
- name: Use Node.js 24
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
- name: Install
run: npm install

View File

@@ -61,10 +61,10 @@ jobs:
- name: Install Composer dependencies
uses: ramsey/composer-install@v2
- name: Use Node.js 20
- name: Use Node.js 24
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
- name: Install
run: npm install
@@ -100,10 +100,10 @@ jobs:
with:
composer-options: --no-dev
- name: Use Node.js 20
- name: Use Node.js 24
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 24
- name: Install
run: npm install

1
.node-version Normal file
View File

@@ -0,0 +1 @@
24

5909
.phpstorm.meta.php Normal file

File diff suppressed because it is too large Load Diff

80
CLAUDE.md Normal file
View File

@@ -0,0 +1,80 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
InvoiceShelf is an open-source invoicing and expense tracking application built with Laravel 13 (PHP 8.4) and Vue 3. It supports multi-company tenancy, customer portals, recurring invoices, and PDF generation.
## Common Commands
### Development
```bash
composer run dev # Starts PHP server, queue listener, log tail, and Vite dev server concurrently
npm run dev # Vite dev server only
npm run build # Production frontend build
```
### Testing
```bash
php artisan test --compact # Run all tests
php artisan test --compact --filter=testName # Run specific test
./vendor/bin/pest --stop-on-failure # Run via Pest directly
make test # Makefile shortcut
```
Tests use SQLite in-memory DB, configured in `phpunit.xml`. Tests seed via `DatabaseSeeder` + `DemoSeeder` in `beforeEach`. Authenticate with `Sanctum::actingAs()` and set the `company` header.
### Code Style
```bash
vendor/bin/pint --dirty --format agent # Fix style on modified PHP files
vendor/bin/pint --test # Check style without fixing (CI uses this)
```
### Artisan Generators
Always use `php artisan make:*` with `--no-interaction` to create new files (models, controllers, migrations, tests, etc.).
## Architecture
### Multi-Tenancy
Every major model has a `company_id` foreign key. The `CompanyMiddleware` sets the active company from the `company` request header. Bouncer authorization is scoped to the company level via `DefaultScope` (`app/Bouncer/Scopes/DefaultScope.php`).
### Authentication
Three guards: `web` (session), `api` (Sanctum tokens for `/api/v1/`), `customer` (session for customer portal). API routes use `auth:sanctum` middleware; customer portal uses `auth:customer`.
### Routing
- **API**: All endpoints under `/api/v1/` in `routes/api.php`, grouped with `auth:sanctum`, `company`, and `bouncer` middleware
- **Web**: `routes/web.php` serves PDF endpoints, auth pages, and catch-all SPA routes (`/admin/{vue?}`, `/{company:slug}/customer/{vue?}`)
### Frontend
- Entry point: `resources/scripts/main.js`
- Vue Router: `resources/scripts/admin/admin-router.js` (admin), `resources/scripts/customer/customer-router.js` (customer portal)
- State: Pinia stores in `resources/scripts/admin/stores/`
- Path aliases: `@` = `resources/`, `$fonts`, `$images` for static assets
- Vite dev server expects `invoiceshelf.test` hostname
### Backend Patterns
- **Authorization**: Silber/Bouncer with policies in `app/Policies/`. Controllers use `$this->authorize()`.
- **Validation**: Form Request classes, never inline validation
- **API responses**: Eloquent API Resources in `app/Http/Resources/`
- **PDF generation**: DomPDF (`GeneratesPdfTrait`) or Gotenberg
- **Email**: Mailable classes with `EmailLog` tracking
- **File storage**: Spatie MediaLibrary, supports local/S3/Dropbox
- **Serial numbers**: `SerialNumberFormatter` service
- **Company settings**: `CompanySetting` model (key-value per company)
### Database
Supports MySQL, PostgreSQL, and SQLite. Prefer Eloquent over raw queries. Use `Model::query()` instead of `DB::`. Use eager loading to prevent N+1 queries.
## Code Conventions
- PHP: snake_case, constructor property promotion, explicit return types, PHPDoc blocks over inline comments
- JS: camelCase
- Always check sibling files for patterns before creating new ones
- Use `config()` helper, never `env()` outside config files
- Every change must have tests (feature tests preferred over unit tests)
- Run `vendor/bin/pint --dirty --format agent` after modifying PHP files
## CI Pipeline
GitHub Actions (`check.yaml`): runs Pint style check, then builds frontend and runs Pest tests on PHP 8.4.

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ class ResetApp extends Command
*
* @var string
*/
protected $description = 'Clean database, database_created and public/storage folder';
protected $description = 'Clean database and public/storage folder';
/**
* Create a new command instance.

View File

@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use App\Space\Updater;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
// Implementation taken from Akaunting - https://github.com/akaunting/akaunting
class UpdateCommand extends Command

View File

@@ -5,6 +5,7 @@
namespace App\Http\Controllers\V1\Admin\Backup;
use App\Jobs\CreateBackupJob;
use App\Models\FileDisk;
use App\Rules\Backup\PathToZip;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -27,6 +28,16 @@ class BackupsController extends ApiController
$configuredBackupDisks = config('backup.backup.destination.disks');
try {
if ($request->file_disk_id) {
$fileDisk = FileDisk::find($request->file_disk_id);
if ($fileDisk) {
$fileDisk->setConfig();
$prefix = env('DYNAMIC_DISK_PREFIX', 'temp_');
config(['backup.backup.destination.disks' => [$prefix.$fileDisk->driver]]);
$configuredBackupDisks = config('backup.backup.destination.disks');
}
}
$backupDestination = BackupDestination::create(config('filesystems.default'), config('backup.backup.name'));
$backups = Cache::remember("backups-{$request->file_disk_id}", now()->addSeconds(4), function () use ($backupDestination) {
@@ -65,7 +76,10 @@ class BackupsController extends ApiController
{
$this->authorize('manage backups');
dispatch(new CreateBackupJob($request->all()))->onQueue(config('backup.queue.name'));
$data = $request->all();
$data['company'] = $request->header('company');
dispatch(new CreateBackupJob($data))->onQueue(config('backup.queue.name'));
return $this->respondSuccess();
}

View File

@@ -61,10 +61,10 @@ class CompaniesController extends Controller
$company = Company::find($request->header('company'));
$this->authorize('transfer company ownership', $company);
if ($user->hasCompany($company->id)) {
if (! $user->hasCompany($company->id)) {
return response()->json([
'success' => false,
'message' => 'User does not belongs to this company.',
'message' => 'User does not belong to this company.',
]);
}

View File

@@ -92,7 +92,11 @@ class CustomersController extends Controller
{
$this->authorize('delete multiple customers');
Customer::deleteCustomers($request->ids);
$ids = Customer::whereCompany()
->whereIn('id', $request->ids)
->pluck('id');
Customer::deleteCustomers($ids);
return response()->json([
'success' => true,

View File

@@ -21,6 +21,7 @@ class CloneEstimateController extends Controller
*/
public function __invoke(Request $request, Estimate $estimate)
{
$this->authorize('view', $estimate);
$this->authorize('create', Estimate::class);
$date = Carbon::now();

View File

@@ -68,7 +68,11 @@ class EstimatesController extends Controller
{
$this->authorize('delete multiple estimates');
Estimate::destroy($request->ids);
$ids = Estimate::whereCompany()
->whereIn('id', $request->ids)
->pluck('id');
Estimate::destroy($ids);
return response()->json([
'success' => true,

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Http\Controllers\V1\Admin\Expense;
use App\Http\Controllers\Controller;
use App\Http\Requests\DuplicateExpenseRequest;
use App\Http\Resources\ExpenseResource;
use App\Models\CompanySetting;
use App\Models\ExchangeRateLog;
use App\Models\Expense;
class DuplicateExpenseController extends Controller
{
/**
* Duplicate an expense, appending " (copy)" to the note (description).
*/
public function __invoke(DuplicateExpenseRequest $request, Expense $expense): ExpenseResource
{
$this->authorize('view', $expense);
$this->authorize('create', Expense::class);
$expense->load('fields');
$companyCurrency = CompanySetting::getSetting('currency', $request->header('company'));
$currentCurrency = $expense->currency_id;
$exchangeRate = $companyCurrency != $currentCurrency ? $expense->exchange_rate : 1;
$notes = trim((string) $expense->notes);
$duplicatedNotes = $notes === '' ? '(copy)' : $notes.' (copy)';
$newExpense = Expense::query()->create([
'expense_date' => $request->validated('expense_date'),
'expense_number' => null,
'expense_category_id' => $expense->expense_category_id,
'payment_method_id' => $expense->payment_method_id,
'amount' => $expense->amount,
'customer_id' => $expense->customer_id,
'notes' => $duplicatedNotes,
'currency_id' => $expense->currency_id,
'creator_id' => $request->user()->id,
'company_id' => $request->header('company'),
'exchange_rate' => $exchangeRate,
'base_amount' => $expense->amount * $exchangeRate,
]);
if ((string) $newExpense->currency_id !== (string) $companyCurrency) {
ExchangeRateLog::addExchangeRateLog($newExpense);
}
if ($expense->fields()->exists()) {
$customFields = [];
foreach ($expense->fields as $data) {
$customFields[] = [
'id' => $data->custom_field_id,
'value' => $data->defaultAnswer,
];
}
$newExpense->addCustomFields($customFields);
}
return new ExpenseResource($newExpense);
}
}

View File

@@ -81,7 +81,11 @@ class ExpensesController extends Controller
{
$this->authorize('delete multiple expenses');
Expense::destroy($request->ids);
$ids = Expense::whereCompany()
->whereIn('id', $request->ids)
->pluck('id');
Expense::destroy($ids);
return response()->json([
'success' => true,

View File

@@ -25,7 +25,8 @@ class SearchController extends Controller
->paginate(10);
if ($user->isOwner()) {
$users = User::applyFilters($request->only(['search']))
$users = User::whereCompany()
->applyFilters($request->only(['search']))
->latest()
->paginate(10);
}

View File

@@ -21,6 +21,7 @@ class CloneInvoiceController extends Controller
*/
public function __invoke(Request $request, Invoice $invoice)
{
$this->authorize('view', $invoice);
$this->authorize('create', Invoice::class);
$date = Carbon::now();

View File

@@ -100,7 +100,11 @@ class InvoicesController extends Controller
{
$this->authorize('delete multiple invoices');
Invoice::deleteInvoices($request->ids);
$ids = Invoice::whereCompany()
->whereIn('id', $request->ids)
->pluck('id');
Invoice::deleteInvoices($ids);
return response()->json([
'success' => true,

View File

@@ -90,7 +90,11 @@ class ItemsController extends Controller
{
$this->authorize('delete multiple items');
Item::destroy($request->ids);
$ids = Item::whereCompany()
->whereIn('id', $request->ids)
->pluck('id');
Item::destroy($ids);
return response()->json([
'success' => true,

View File

@@ -73,7 +73,11 @@ class PaymentsController extends Controller
{
$this->authorize('delete multiple payments');
Payment::deletePayments($request->ids);
$ids = Payment::whereCompany()
->whereIn('id', $request->ids)
->pluck('id');
Payment::deletePayments($ids);
return response()->json([
'success' => true,

View File

@@ -84,7 +84,11 @@ class RecurringInvoiceController extends Controller
{
$this->authorize('delete multiple recurring invoices');
RecurringInvoice::deleteRecurringInvoice($request->ids);
$ids = RecurringInvoice::whereCompany()
->whereIn('id', $request->ids)
->pluck('id');
RecurringInvoice::deleteRecurringInvoice($ids);
return response()->json([
'success' => true,

View File

@@ -7,11 +7,12 @@ use App\Models\Company;
use App\Models\CompanySetting;
use App\Models\Currency;
use App\Models\Expense;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\App;
use PDF;
class ExpensesReportController extends Controller
{
@@ -19,7 +20,7 @@ class ExpensesReportController extends Controller
* Handle the incoming request.
*
* @param string $hash
* @return JsonResponse
* @return View|Response
*/
public function __invoke(Request $request, $hash)
{
@@ -31,14 +32,26 @@ class ExpensesReportController extends Controller
App::setLocale($locale);
$expenseCategories = Expense::with('category')
// Fetch individual expenses (filtered and ordered by date), then group by category
$expenses = Expense::with('category')
->whereCompanyId($company->id)
->applyFilters($request->only(['from_date', 'to_date']))
->expensesAttributes()
->applyFilters($request->only(['from_date', 'to_date', 'expense_category_id']))
->orderBy('expense_date', 'asc')
->get();
$totalAmount = 0;
foreach ($expenseCategories as $category) {
$totalAmount += $category->total_amount;
$totalAmount = $expenses->sum('base_amount');
$grouped = $expenses->groupBy(function ($item) {
return $item->category ? $item->category->name : trans('expenses.uncategorized');
});
$expenseGroups = collect();
foreach ($grouped as $categoryName => $group) {
$expenseGroups->push([
'name' => $categoryName,
'expenses' => $group,
'total' => $group->sum('base_amount'),
]);
}
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
@@ -62,7 +75,7 @@ class ExpensesReportController extends Controller
->get();
view()->share([
'expenseCategories' => $expenseCategories,
'expenseGroups' => $expenseGroups,
'colorSettings' => $colorSettings,
'totalExpense' => $totalAmount,
'company' => $company,
@@ -70,7 +83,7 @@ class ExpensesReportController extends Controller
'to_date' => $to_date,
'currency' => $currency,
]);
$pdf = PDF::loadView('app.pdf.reports.expenses');
$pdf = Pdf::loadView('app.pdf.reports.expenses');
if ($request->has('preview')) {
return view('app.pdf.reports.expenses');

View File

@@ -165,11 +165,11 @@ class MailConfigurationController extends Controller
switch ($driver) {
case 'smtp':
$MailData = array_merge($MailData, [
'mail_host' => $mailSettings['mail_host'] ?? '',
'mail_port' => $mailSettings['mail_port'] ?? '',
'mail_username' => $mailSettings['mail_username'] ?? '',
'mail_password' => $mailSettings['mail_password'] ?? '',
'mail_encryption' => $mailSettings['mail_encryption'] ?? 'none',
'mail_host' => $mailSettings['mail_host'] ?? config('mail.mailers.smtp.host', ''),
'mail_port' => $mailSettings['mail_port'] ?? config('mail.mailers.smtp.port', ''),
'mail_username' => $mailSettings['mail_username'] ?? config('mail.mailers.smtp.username', ''),
'mail_password' => $mailSettings['mail_password'] ?? config('mail.mailers.smtp.password', ''),
'mail_encryption' => $mailSettings['mail_encryption'] ?? config('mail.mailers.smtp.encryption', 'none'),
'mail_scheme' => $mailSettings['mail_scheme'] ?? '',
'mail_url' => $mailSettings['mail_url'] ?? '',
'mail_timeout' => $mailSettings['mail_timeout'] ?? '',

View File

@@ -25,14 +25,15 @@ class UsersController extends Controller
$user = $request->user();
$users = User::applyFilters($request->all())
$users = User::whereCompany()
->applyFilters($request->all())
->where('id', '<>', $user->id)
->latest()
->paginate($limit);
return UserResource::collection($users)
->additional(['meta' => [
'user_total_count' => User::count(),
'user_total_count' => User::whereCompany()->count(),
]]);
}

View File

@@ -48,8 +48,9 @@ class DatabaseConfigurationController extends Controller
public function getDatabaseEnvironment(Request $request)
{
$databaseData = [];
$connection = $request->connection ?? config('database.default');
switch ($request->connection) {
switch ($connection) {
case 'sqlite':
$databaseData = [
'database_connection' => 'sqlite',

View File

@@ -3,7 +3,6 @@
namespace App\Http\Controllers\V1\Installation;
use App\Http\Controllers\Controller;
use App\Space\InstallUtils;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -16,10 +15,6 @@ class FinishController extends Controller
*/
public function __invoke(Request $request)
{
if (! InstallUtils::createDbMarker()) {
\Log::error('Install: Unable to create db marker.');
}
return response()->json(['success' => true]);
}
}

View File

@@ -17,7 +17,7 @@ class OnboardingWizardController extends Controller
*/
public function getStep(Request $request)
{
if (! InstallUtils::dbMarkerExists()) {
if (! InstallUtils::isDbCreated()) {
return response()->json([
'profile_complete' => 0,
'profile_language' => 'en',

View File

@@ -17,7 +17,11 @@ class InstallationMiddleware
*/
public function handle(Request $request, Closure $next): Response
{
if (! InstallUtils::isDbCreated() || Setting::getSetting('profile_complete') !== 'COMPLETED') {
try {
if (! InstallUtils::isDbCreated() || Setting::getSetting('profile_complete') !== 'COMPLETED') {
return redirect('/installation');
}
} catch (\Exception $e) {
return redirect('/installation');
}

View File

@@ -17,9 +17,13 @@ class RedirectIfInstalled
*/
public function handle(Request $request, Closure $next): Response
{
if (InstallUtils::dbMarkerExists()) {
if (Setting::getSetting('profile_complete') === 'COMPLETED') {
return redirect('login');
if (InstallUtils::isDbCreated()) {
try {
if (Setting::getSetting('profile_complete') === 'COMPLETED') {
return redirect('login');
}
} catch (\Exception $e) {
// Settings table may not exist yet during installation
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class DuplicateExpenseRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, array<int, string>>
*/
public function rules(): array
{
return [
'expense_date' => [
'required',
'date_format:Y-m-d',
],
];
}
}

View File

@@ -2,13 +2,12 @@
namespace App\Jobs;
use App\Models\FileDisk;
use App\Space\BackupConfigurationFactory;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\Backup\Config\Config;
use Spatie\Backup\Tasks\Backup\BackupJobFactory;
class CreateBackupJob implements ShouldQueue
@@ -25,7 +24,7 @@ class CreateBackupJob implements ShouldQueue
*
* @return void
*/
public function __construct($data = '')
public function __construct($data = [])
{
$this->data = $data;
}
@@ -35,14 +34,7 @@ class CreateBackupJob implements ShouldQueue
*/
public function handle(): void
{
$fileDisk = FileDisk::find($this->data['file_disk_id']);
$fileDisk->setConfig();
$prefix = env('DYNAMIC_DISK_PREFIX', 'temp_');
config(['backup.backup.destination.disks' => [$prefix.$fileDisk->driver]]);
$config = Config::fromArray(config('backup'));
$config = BackupConfigurationFactory::make($this->data);
$backupJob = BackupJobFactory::createFromConfig($config);
if (! defined('SIGINT')) {
$backupJob->disableSignals();

View File

@@ -8,7 +8,6 @@ use App\Facades\PDF;
use App\Mail\SendEstimateMail;
use App\Services\SerialNumberFormatter;
use App\Space\PdfTemplateUtils;
use App\Support\PdfHtmlSanitizer;
use App\Traits\GeneratesPdfTrait;
use App\Traits\HasCustomFieldsTrait;
use Carbon\Carbon;
@@ -476,7 +475,7 @@ class Estimate extends Model implements HasMedia
public function getNotes()
{
return PdfHtmlSanitizer::sanitize($this->getFormattedString($this->notes));
return $this->getFormattedString($this->notes);
}
public function getEmailAttachmentSetting()

View File

@@ -8,7 +8,6 @@ use App\Facades\PDF;
use App\Mail\SendInvoiceMail;
use App\Services\SerialNumberFormatter;
use App\Space\PdfTemplateUtils;
use App\Support\PdfHtmlSanitizer;
use App\Traits\GeneratesPdfTrait;
use App\Traits\HasCustomFieldsTrait;
use Carbon\Carbon;
@@ -657,7 +656,7 @@ class Invoice extends Model implements HasMedia
public function getNotes()
{
return PdfHtmlSanitizer::sanitize($this->getFormattedString($this->notes));
return $this->getFormattedString($this->notes);
}
public function getEmailString($body)

View File

@@ -6,7 +6,6 @@ use App\Facades\Hashids;
use App\Jobs\GeneratePaymentPdfJob;
use App\Mail\SendPaymentMail;
use App\Services\SerialNumberFormatter;
use App\Support\PdfHtmlSanitizer;
use App\Traits\GeneratesPdfTrait;
use App\Traits\HasCustomFieldsTrait;
use Barryvdh\DomPDF\Facade\Pdf as PDF;
@@ -434,7 +433,7 @@ class Payment extends Model implements HasMedia
public function getNotes()
{
return PdfHtmlSanitizer::sanitize($this->getFormattedString($this->notes));
return $this->getFormattedString($this->notes);
}
public function getEmailBody($body)

View File

@@ -213,6 +213,13 @@ class User extends Authenticatable implements HasMedia
return $query->where('email', 'LIKE', '%'.$email.'%');
}
public function scopeWhereCompany($query)
{
return $query->whereHas('companies', function ($q) {
$q->where('company_id', request()->header('company'));
});
}
public function scopePaginateData($query, $limit)
{
if ($limit == 'all') {

View File

@@ -32,7 +32,7 @@ class CustomerPolicy
*/
public function view(User $user, Customer $customer): bool
{
if (BouncerFacade::can('view-customer', $customer)) {
if (BouncerFacade::can('view-customer', $customer) && $user->hasCompany($customer->company_id)) {
return true;
}
@@ -60,7 +60,7 @@ class CustomerPolicy
*/
public function update(User $user, Customer $customer): bool
{
if (BouncerFacade::can('edit-customer', $customer)) {
if (BouncerFacade::can('edit-customer', $customer) && $user->hasCompany($customer->company_id)) {
return true;
}
@@ -74,7 +74,7 @@ class CustomerPolicy
*/
public function delete(User $user, Customer $customer): bool
{
if (BouncerFacade::can('delete-customer', $customer)) {
if (BouncerFacade::can('delete-customer', $customer) && $user->hasCompany($customer->company_id)) {
return true;
}
@@ -88,7 +88,7 @@ class CustomerPolicy
*/
public function restore(User $user, Customer $customer): bool
{
if (BouncerFacade::can('delete-customer', $customer)) {
if (BouncerFacade::can('delete-customer', $customer) && $user->hasCompany($customer->company_id)) {
return true;
}
@@ -102,7 +102,7 @@ class CustomerPolicy
*/
public function forceDelete(User $user, Customer $customer): bool
{
if (BouncerFacade::can('delete-customer', $customer)) {
if (BouncerFacade::can('delete-customer', $customer) && $user->hasCompany($customer->company_id)) {
return true;
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Space;
use App\Models\CompanySetting;
use App\Models\FileDisk;
use Exception;
use Spatie\Backup\Config\Config;
class BackupConfigurationFactory
{
public static function make($data = []): Config
{
if (blank($data['company'] ?? null)) {
throw new Exception('The Company ID is missig');
}
if (blank($data['file_disk_id'] ?? null)) {
throw new Exception('No file disk selected');
}
$fileDisk = FileDisk::find($data['file_disk_id']);
$fileDisk->setConfig();
$prefix = env('DYNAMIC_DISK_PREFIX', 'temp_');
config(['backup.backup.destination.disks' => [$prefix.$fileDisk->driver]]);
$companyNotificationEmail = CompanySetting::getSetting('notification_email', $data['company']);
if ($companyNotificationEmail) {
config(['backup.notifications.mail.to' => $companyNotificationEmail]);
}
$config = Config::fromArray(config('backup'));
return $config;
}
}

View File

@@ -5,8 +5,6 @@ namespace App\Space;
use App\Models\Setting;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use League\Flysystem\FilesystemException;
class InstallUtils
{
@@ -17,7 +15,7 @@ class InstallUtils
*/
public static function isDbCreated()
{
return self::dbMarkerExists() && self::tableExists('users');
return self::tableExists('users');
}
/**
@@ -44,54 +42,6 @@ class InstallUtils
return $cache[$table];
}
/**
* Check if database created marker exists
*
* @return bool
*/
public static function dbMarkerExists()
{
try {
return \Storage::disk('local')->has('database_created');
} catch (FilesystemException $e) {
Log::error('Unable to verify db marker: '.$e->getMessage());
}
return false;
}
/**
* Creates the database marker
*
* @return bool
*/
public static function createDbMarker()
{
try {
return \Storage::disk('local')->put('database_created', time());
} catch (\Exception $e) {
Log::error('Unable to create db marker: '.$e->getMessage());
}
return false;
}
/**
* Deletes the database marker
*
* @return bool
*/
public static function deleteDbMarker()
{
try {
return \Storage::disk('local')->delete('database_created');
} catch (\Exception $e) {
Log::error('Unable to delete db marker: '.$e->getMessage());
}
return false;
}
/**
* Set the app version
*

View File

@@ -19,6 +19,9 @@ final class PdfHtmlSanitizer
return '';
}
// Legacy/invalid `</br>` is dropped by libxml and collapses lines in PDF output; normalize to `<br />`.
$html = str_replace('</br>', '<br />', $html);
$allowedTags = '<br><br/><p><b><strong><i><em><u><ol><ul><li><table><tr><td><th><thead><tbody><tfoot><h1><h2><h3><h4><blockquote>';
$html = strip_tags($html, $allowedTags);

View File

@@ -5,6 +5,7 @@ namespace App\Traits;
use App\Models\Address;
use App\Models\CompanySetting;
use App\Models\FileDisk;
use App\Support\PdfHtmlSanitizer;
use Carbon\Carbon;
use Illuminate\Support\Facades\App;
@@ -180,8 +181,12 @@ trait GeneratesPdfTrait
$str = str_replace('<p>', '', $str);
$str = str_replace('</p>', '</br>', $str);
$str = str_replace('</p>', '<br />', $str);
return $str;
// Sanitize the assembled HTML to strip any SSRF vectors that may have
// entered through user-supplied address fields, customer names, or
// custom field values. Notes also pass through this method, so they
// get the same treatment without needing a separate wrapper.
return PdfHtmlSanitizer::sanitize($str);
}
}

View File

@@ -9,15 +9,12 @@
"type": "project",
"require": {
"php": "^8.4",
"aws/aws-sdk-php": "^3.336",
"barryvdh/laravel-dompdf": "^v3.0",
"doctrine/dbal": "^4.2",
"dragonmantank/cron-expression": "^v3.4",
"gotenberg/gotenberg-php": "^2.8",
"guzzlehttp/guzzle": "^7.9",
"hashids/hashids": "^5.0",
"invoiceshelf/modules": "^1.0.0",
"jasonmccreary/laravel-test-assertions": "^v2.4",
"laravel/framework": "^13.0",
"laravel/helpers": "^1.7",
"laravel/sanctum": "^4.0",
@@ -36,6 +33,7 @@
"require-dev": {
"barryvdh/laravel-ide-helper": "^3.5",
"fakerphp/faker": "^1.23",
"jasonmccreary/laravel-test-assertions": "^2.9",
"laravel/boost": "^2.3",
"laravel/pint": "^1.13",
"laravel/sail": "^1.41",
@@ -83,7 +81,11 @@
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
]
],
"ide-helper": [
"@php artisan ide-helper:generate",
"@php artisan ide-helper:meta"
]
},
"extra": {
"laravel": {

3915
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -37,6 +37,15 @@ return [
'report' => false,
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
'report' => false,
],
's3' => [
'driver' => 's3',
'key' => env('AWS_KEY'),

View File

@@ -16,7 +16,7 @@ return [
/*
* Minimum php version.
*/
'min_php_version' => '8.2.0',
'min_php_version' => '8.4.0',
/*
* Minimum mysql version.

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('tax_types', function (Blueprint $table) {
$table->decimal('percent', 5, 3)->nullable()->change();
});
Schema::table('taxes', function (Blueprint $table) {
$table->decimal('percent', 5, 3)->nullable()->change();
});
}
public function down(): void
{
Schema::table('tax_types', function (Blueprint $table) {
$table->decimal('percent', 5, 2)->nullable()->change();
});
Schema::table('taxes', function (Blueprint $table) {
$table->decimal('percent', 5, 2)->nullable()->change();
});
}
};

View File

@@ -8,7 +8,6 @@ use App\Models\CompanySetting;
use App\Models\Customer;
use App\Models\Setting;
use App\Models\User;
use App\Space\InstallUtils;
use Illuminate\Database\Seeder;
use Silber\Bouncer\BouncerFacade;
@@ -71,8 +70,5 @@ class DemoSeeder extends Seeder
// Mark profile setup as complete
Setting::setSetting('profile_complete', 'COMPLETED');
// Create installation marker
InstallUtils::createDbMarker();
}
}

View File

@@ -1,11 +1,11 @@
FROM --platform=$BUILDPLATFORM node AS static_builder
FROM --platform=$BUILDPLATFORM node:24 AS static_builder
WORKDIR /var/www/html
COPY . /var/www/html
RUN yarn && yarn build
FROM serversideup/php:8.4-fpm-alpine AS base
USER root
RUN apk add --no-cache sqlite
RUN apk add --no-cache bash nano mariadb-client postgresql-client sqlite
RUN install-php-extensions exif
RUN install-php-extensions pgsql
RUN install-php-extensions sqlite3

View File

@@ -1,11 +1,11 @@
FROM --platform=$BUILDPLATFORM node:20 AS static_builder
FROM --platform=$BUILDPLATFORM node:24 AS static_builder
WORKDIR /var/www/html
COPY . /var/www/html
RUN yarn && yarn build
FROM serversideup/php:8.4-fpm-nginx-alpine AS base
USER root
RUN apk add --no-cache bash nano
RUN apk add --no-cache bash nano mariadb-client postgresql-client sqlite
RUN install-php-extensions exif
RUN install-php-extensions pgsql
RUN install-php-extensions sqlite3
@@ -19,6 +19,10 @@ FROM serversideup/php:8.4-fpm-nginx-alpine AS base
RUN install-php-extensions intl
RUN install-php-extensions curl
# Copy entrypoint and inject script, and make sure they are executable
COPY --chmod=755 docker/production/inject.sh /inject.sh
COPY --chmod=755 docker/production/entrypoint.d/ /etc/entrypoint.d/
FROM base AS production
ENV AUTORUN_ENABLED=true
ENV PHP_OPCACHE_ENABLE=1
@@ -36,7 +40,3 @@ FROM base AS production
COPY --from=static_builder --chown=www-data:www-data /var/www/html/public /var/www/html/public
COPY --chown=www-data:www-data . /var/www/html
RUN composer install --prefer-dist --no-dev --optimize-autoloader
# Copy entrypoint and inject script, and make sure they are executable
COPY --chmod=755 docker/production/inject.sh /inject.sh
COPY --chmod=755 docker/production/entrypoint.d/ /etc/entrypoint.d/

View File

@@ -33,8 +33,15 @@ if [ "$DB_CONNECTION" = "sqlite" ] || [ -z "$DB_CONNECTION" ]; then
chown www-data:www-data "$DB_DATABASE"
fi
echo "**** Setting up artisan permissions ****"
echo "**** Setting up folder permissions ****"
chmod +x artisan
chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache
if [ ! -L /var/www/html/public/storage ]; then
echo "**** Creating storage symlink (public/storage) ****"
./artisan storage:link --force -n || true
fi
if ! grep -q "APP_KEY" /var/www/html/.env
then

13
eslint.config.mjs Normal file
View File

@@ -0,0 +1,13 @@
import pluginVue from 'eslint-plugin-vue'
import eslintConfigPrettier from 'eslint-config-prettier'
export default [
...pluginVue.configs['flat/recommended'],
eslintConfigPrettier,
{
files: ['resources/scripts/**/*.{js,vue}'],
rules: {
'vue/no-mutating-props': 'off',
},
},
]

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "تواصل",
"category": "الفئة",
"uncategorized": "Uncategorized",
"from_date": "من تاريخ",
"to_date": "حتى تاريخ",
"expense_date": "التاريخ",
@@ -1326,7 +1327,8 @@
"finishing_update": "تحديث التشطيب",
"update_failed": "فشل التحديث",
"update_failed_text": "آسف! فشل التحديث الخاص بك في: {step} خطوة",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "النسخ الاحتياطي | النسخ الاحتياطية",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "اجمالي الاداءات",
"pdf_tax_types_label": "أنواع الضرائب",
"pdf_expenses_label": "النفقات",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "مطلوب من,",
"pdf_ship_to": "يشحن إلى,",
"pdf_received_from": "تم الاستلام من:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Měna",
"contact": "Kontakt",
"category": "Kategorie",
"uncategorized": "Uncategorized",
"from_date": "Od data",
"to_date": "Do data",
"expense_date": "Datum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Dokončování aktualizace",
"update_failed": "Aktualizace se nezdařila",
"update_failed_text": "Omlouváme se! Aktualizace se nezdařila v {step}. kroku",
"update_warning": "Všechny soubory aplikace a výchozí soubory šablon budou přepsány při aktualizaci aplikace pomocí tohoto nástroje. Před aktualizací si prosím zálohujte šablony a databázi."
"update_warning": "Všechny soubory aplikace a výchozí soubory šablon budou přepsány při aktualizaci aplikace pomocí tohoto nástroje. Před aktualizací si prosím zálohujte šablony a databázi.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Záloha | Zálohy",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "DANĚ CELKEM",
"pdf_tax_types_label": "Typy daní",
"pdf_expenses_label": "Výdaje",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Odběratel",
"pdf_ship_to": "Příjemce",
"pdf_received_from": "Přijato od:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Währung",
"contact": "Kontakt",
"category": "Kategorie",
"uncategorized": "Uncategorized",
"from_date": "Von Datum",
"to_date": "bis Datum",
"expense_date": "Datum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Update beenden",
"update_failed": "Update fehlgeschlagen",
"update_failed_text": "Es tut uns leid! Ihr Update ist am folgenden Schritt fehlgeschlagen: {step}",
"update_warning": "Alle Anwendungsdateien und Standardvorlagen werden überschrieben, wenn Sie die Anwendung mit diesem Hilfsprogramm aktualisieren. Bitte machen Sie vor dem Update ein Backup Ihrer Vorlagen & Datenbank."
"update_warning": "Alle Anwendungsdateien und Standardvorlagen werden überschrieben, wenn Sie die Anwendung mit diesem Hilfsprogramm aktualisieren. Bitte machen Sie vor dem Update ein Backup Ihrer Vorlagen & Datenbank.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Sicherung | Sicherungen",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "Gesamte Umsatzsteuer",
"pdf_tax_types_label": "Steuersätze",
"pdf_expenses_label": "Ausgaben",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Rechnungsanschrift",
"pdf_ship_to": "Lieferanschrift",
"pdf_received_from": "Erhalten von:",

View File

@@ -652,6 +652,7 @@
"currency": "Νόμισμα",
"contact": "Επικοινωνία",
"category": "Κατηγορία",
"uncategorized": "Uncategorized",
"from_date": "Από Ημερομηνία",
"to_date": "Έως ημερομηνία",
"expense_date": "Ημερομηνία",
@@ -1326,7 +1327,8 @@
"finishing_update": "Ολοκλήρωση Ενημέρωσης",
"update_failed": "Αποτυχία ενημέρωσης",
"update_failed_text": "Συγνώμη! Η ενημέρωσή σας απέτυχε σε: {step} βήμα",
"update_warning": "Όλα τα αρχεία εφαρμογών και τα προεπιλεγμένα αρχεία προτύπων θα αντικατασταθούν όταν ενημερώνετε την εφαρμογή χρησιμοποιώντας αυτό το βοηθητικό πρόγραμμα. Παρακαλώ πάρτε ένα αντίγραφο ασφαλείας των προτύπων και της βάσης δεδομένων σας πριν από την ενημέρωση."
"update_warning": "Όλα τα αρχεία εφαρμογών και τα προεπιλεγμένα αρχεία προτύπων θα αντικατασταθούν όταν ενημερώνετε την εφαρμογή χρησιμοποιώντας αυτό το βοηθητικό πρόγραμμα. Παρακαλώ πάρτε ένα αντίγραφο ασφαλείας των προτύπων και της βάσης δεδομένων σας πριν από την ενημέρωση.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Αντίγραφο Ασφαλείας \"Αντίγραφα Ασφαλείας",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "ΣΥΝΟΛΟ ΦΟΡΟΥ",
"pdf_tax_types_label": "Φορολογική κλάση",
"pdf_expenses_label": "Έξοδα",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Χρέωση σε,",
"pdf_ship_to": "Αποστολή σε,",
"pdf_received_from": "Λήψη από",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -676,6 +677,10 @@
"no_expenses": "No expenses yet!",
"list_of_expenses": "This section will contain the list of expenses.",
"confirm_delete": "You will not be able to recover this Expense | You will not be able to recover these Expenses",
"duplicate_expense": "Duplicate",
"duplicate_expense_title": "Duplicate expense",
"duplicate_expense_modal_hint": "Change the date if you need to. (copy) is added to the note.",
"duplicated_message": "Expense duplicated successfully",
"created_message": "Expense created successfully",
"updated_message": "Expense updated successfully",
"deleted_message": "Expense deleted successfully | Expenses deleted successfully",
@@ -1326,7 +1331,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1654,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Divisa",
"contact": "Contacto",
"category": "Categoría",
"uncategorized": "Uncategorized",
"from_date": "Desde la fecha",
"to_date": "Hasta la fecha",
"expense_date": "Fecha",
@@ -1326,7 +1327,8 @@
"finishing_update": "Actualización final",
"update_failed": "Actualización fallida",
"update_failed_text": "¡Lo siento! Su actualización falló el: {step} paso",
"update_warning": "Todos los archivos y temas predeterminados se sobreescribirán cuando actualice la aplicación a través de esta utilidad. Por favor, cree una copia de seguridad de sus temas y base de datos antes de actualizar."
"update_warning": "Todos los archivos y temas predeterminados se sobreescribirán cuando actualice la aplicación a través de esta utilidad. Por favor, cree una copia de seguridad de sus temas y base de datos antes de actualizar.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Copia de seguridad | Copias de seguridad",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "IMPUESTO TOTAL",
"pdf_tax_types_label": "Tipos de impuestos",
"pdf_expenses_label": "Gastos",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Cobrar a,",
"pdf_ship_to": "Enviar a,",
"pdf_received_from": "Recibido de:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Valuutta",
"contact": "Yhteyshenkilö",
"category": "Luokka",
"uncategorized": "Uncategorized",
"from_date": "Päivästä",
"to_date": "Päivään",
"expense_date": "Päivämäärä",
@@ -1326,7 +1327,8 @@
"finishing_update": "Lopetetaan päivitys",
"update_failed": "Päivitys epäonnistui",
"update_failed_text": "Sorry! Päivityksesi epäonnistui : {step} vaiheessa",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Varmuuskopio | Varmuuskopiot",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "ALV YHTEENSÄ",
"pdf_tax_types_label": "ALV Verokannat",
"pdf_expenses_label": "Kulut",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Laskutetaan,",
"pdf_ship_to": "Toimitetaan,",
"pdf_received_from": "Vastaanotettu:",

View File

@@ -652,6 +652,7 @@
"currency": "Devise",
"contact": "Contact",
"category": "Catégorie",
"uncategorized": "Uncategorized",
"from_date": "Du",
"to_date": "Au",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finalisation de la mise à jour",
"update_failed": "Échec de la mise à jour",
"update_failed_text": "Désolé ! Votre mise à jour a échoué à: {step} étape",
"update_warning": "Cet utilitaire va écraser tous les fichiers et templates de l'application. Veuillez faire une sauvegarde de vos templates et de la base de donnée avant de faire la mise à jour."
"update_warning": "Cet utilitaire va écraser tous les fichiers et templates de l'application. Veuillez faire une sauvegarde de vos templates et de la base de donnée avant de faire la mise à jour.",
"requirements_not_met": "La mise à jour ne peut pas continuer car certaines exigences système ne sont pas respectées (y compris la version PHP minimale). Veuillez corriger les exigences en échec puis réessayer."
},
"backup": {
"title": "Sauvegarde | Sauvegardes",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAXES",
"pdf_tax_types_label": "Taxe",
"pdf_expenses_label": "Dépenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Facturer à",
"pdf_ship_to": "Expédier à",
"pdf_received_from": "Reçu de :",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -35,7 +35,7 @@
"yes": "हां",
"no": "नहीं",
"sort_by": "इसके अनुसार क्रमबद्ध करें",
"ascending": "आरोही",
"ascending": "बढ़ते क्रम में",
"descending": "उतरते",
"subject": "विषय",
"body": "बॉडी",
@@ -652,6 +652,7 @@
"currency": "मुद्रा",
"contact": "संपर्क",
"category": "वर्ग",
"uncategorized": "Uncategorized",
"from_date": "इस तारीख से",
"to_date": "इस तारीख तक",
"expense_date": "दिनांक",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Valuta",
"contact": "Kontakt",
"category": "Kategorija",
"uncategorized": "Uncategorized",
"from_date": "Datum od",
"to_date": "Datum do",
"expense_date": "Datum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Završavanje ažuriranja",
"update_failed": "Neuspešno ažuriranje",
"update_failed_text": "Žao mi je! Tvoje ažuriranje nije uspelo na koraku broj: {step} korak",
"update_warning": "Svi dokumenti i predlošci programa će biti obrisani korištenjem ove funkcije. Molimo napravite sigurnosnu kopiju svojih predložaka i baze podataka prije ažuriranja."
"update_warning": "Svi dokumenti i predlošci programa će biti obrisani korištenjem ove funkcije. Molimo napravite sigurnosnu kopiju svojih predložaka i baze podataka prije ažuriranja.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Sigurnosna kopija | Sigurnosne kopije",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "UKUPNO POREZ",
"pdf_tax_types_label": "Vrsta Poreza",
"pdf_expenses_label": "Rashodi",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Račun za,",
"pdf_ship_to": "Isporučiti za,",
"pdf_received_from": "Poslat od strane:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Mata Uang",
"contact": "Kontak",
"category": "Kategori",
"uncategorized": "Uncategorized",
"from_date": "Dari Tanggal",
"to_date": "Sampai Tanggal",
"expense_date": "Tanggal",
@@ -1326,7 +1327,8 @@
"finishing_update": "Menyelesaikan Pembaruan",
"update_failed": "Pembaruan Gagal",
"update_failed_text": "Maaf! Pembaruan Anda gagal pada langkah : {step}",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL PAJAK",
"pdf_tax_types_label": "Jenis Pajak",
"pdf_expenses_label": "Pengeluaran",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Ditagih ke,",
"pdf_ship_to": "Dikirim ke,",
"pdf_received_from": "Diterima dari:",

View File

@@ -652,6 +652,7 @@
"currency": "Valuta",
"contact": "Contatto",
"category": "Categoria",
"uncategorized": "Uncategorized",
"from_date": "Dalla Data",
"to_date": "Alla Data",
"expense_date": "Data",
@@ -1326,7 +1327,8 @@
"finishing_update": "Aggiornamento di finitura",
"update_failed": "Aggiornamento non riuscito",
"update_failed_text": "Scusate! L'aggiornamento non è riuscito il: passaggio {step}",
"update_warning": "Tutti i file dell'applicazione e i file dei modelli predefiniti verranno sovrascritti quando si aggiorna l'applicazione tramite questa utility. Si prega di eseguire un backup dei modelli e del database prima di effettuare l'aggiornamento."
"update_warning": "Tutti i file dell'applicazione e i file dei modelli predefiniti verranno sovrascritti quando si aggiorna l'applicazione tramite questa utility. Si prega di eseguire un backup dei modelli e del database prima di effettuare l'aggiornamento.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTALE IMPOSTA",
"pdf_tax_types_label": "Tipi di Tasse",
"pdf_expenses_label": "Uscite",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Fattura a,",
"pdf_ship_to": "Invia a,",
"pdf_received_from": "Ricevuto da:",

View File

@@ -652,6 +652,7 @@
"currency": "通貨",
"contact": "連絡先",
"category": "カテゴリ",
"uncategorized": "Uncategorized",
"from_date": "開始日",
"to_date": "終了日",
"expense_date": "日時",
@@ -1326,7 +1327,8 @@
"finishing_update": "アップデート完了",
"update_failed": "アップデートに失敗しました",
"update_failed_text": "申し訳ありません。更新に失敗しました: {step} ステップ",
"update_warning": "このユーティリティを使用してアプリケーションを更新するとすべてのアプリケーションファイルと既定のテンプレートファイルが上書きされます。更新する前にテンプレートとデータベースのバックアップを作成してください。"
"update_warning": "このユーティリティを使用してアプリケーションを更新するとすべてのアプリケーションファイルと既定のテンプレートファイルが上書きされます。更新する前にテンプレートとデータベースのバックアップを作成してください。",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "バックアップ | バックアップ",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "合計税額",
"pdf_tax_types_label": "税の種類",
"pdf_expenses_label": "支出",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "請求先",
"pdf_ship_to": "配送先",
"pdf_received_from": "受信元:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Data",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Mokesčių tipai",
"pdf_expenses_label": "Išlaidos",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Siųsti į,",
"pdf_received_from": "Gauta nuo:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Kontakti",
"category": "Kategorija",
"uncategorized": "Uncategorized",
"from_date": "Datums no",
"to_date": "Datums līdz",
"expense_date": "Datums",
@@ -1326,7 +1327,8 @@
"finishing_update": "Pabeidz atjauninājumu",
"update_failed": "Atjaunināšana neizdevās",
"update_failed_text": "Atvainojiet! Jūsu atjauninājuma laikā notika kļūda: {step}. solī",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "NODOKĻI KOPĀ",
"pdf_tax_types_label": "Nodokļu veidi",
"pdf_expenses_label": "Izdevumi",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Saņēmējs,",
"pdf_ship_to": "Piegādes adrese,",
"pdf_received_from": "Saņemts no:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Valuta",
"contact": "Contact",
"category": "Categorie",
"uncategorized": "Uncategorized",
"from_date": "Van datum",
"to_date": "Tot datum",
"expense_date": "Datum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Afwerking Update",
"update_failed": "Update mislukt",
"update_failed_text": "Sorry! Je update is mislukt op: {step} step ",
"update_warning": "Alle applicatiebestanden en de standaard sjabloonbestanden worden overschreven wanneer u de applicatie aan de hand van dit hulpprogramma bijwerkt. Maak een reservekopie van uw sjabloonbestanden en databank voordat u verder gaat."
"update_warning": "Alle applicatiebestanden en de standaard sjabloonbestanden worden overschreven wanneer u de applicatie aan de hand van dit hulpprogramma bijwerkt. Maak een reservekopie van uw sjabloonbestanden en databank voordat u verder gaat.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTALE BELASTINGEN",
"pdf_tax_types_label": "Belastingtypen",
"pdf_expenses_label": "Uitgaven",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Aan,",
"pdf_ship_to": "Verzend naar,",
"pdf_received_from": "Ontvangen van:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Waluta",
"contact": "Kontakt",
"category": "Kategoria",
"uncategorized": "Uncategorized",
"from_date": "Od daty",
"to_date": "Do daty",
"expense_date": "Data",
@@ -1326,7 +1327,8 @@
"finishing_update": "Kończenie aktualizacji",
"update_failed": "Aktualizacja nie powiodła się",
"update_failed_text": "Przepraszamy! Twoja aktualizacja nie powiodła się w kroku: {step}",
"update_warning": "Wszystkie pliki aplikacji i domyślne pliki szablonu zostaną nadpisane podczas aktualizacji aplikacji przy użyciu tego narzędzia. Przed aktualizacją wykonaj kopię zapasową szablonów i bazy danych."
"update_warning": "Wszystkie pliki aplikacji i domyślne pliki szablonu zostaną nadpisane podczas aktualizacji aplikacji przy użyciu tego narzędzia. Przed aktualizacją wykonaj kopię zapasową szablonów i bazy danych.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Kopia zapasowa | Kopie zapasowe",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "CAŁKOWITY PODATEK",
"pdf_tax_types_label": "Rodzaje podatku",
"pdf_expenses_label": "Wydatki",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Wystawiono dla",
"pdf_ship_to": "Wysyłka do",
"pdf_received_from": "Otrzymane od:",

View File

@@ -652,6 +652,7 @@
"currency": "Moeda",
"contact": "Contato",
"category": "Categoria",
"uncategorized": "Uncategorized",
"from_date": "A partir da Data",
"to_date": "Até a Data",
"expense_date": "Data",
@@ -1326,7 +1327,8 @@
"finishing_update": "Atualização de acabamento",
"update_failed": "Atualização falhou",
"update_failed_text": "Desculpa! Sua atualização falhou em: {step} step",
"update_warning": "Todos os arquivos do aplicativo e modelos padrão serão sobrescritos ao atualizar o aplicativo usando esta ferramenta. Faça backup de seus modelos e banco de dados antes de atualizar."
"update_warning": "Todos os arquivos do aplicativo e modelos padrão serão sobrescritos ao atualizar o aplicativo usando esta ferramenta. Faça backup de seus modelos e banco de dados antes de atualizar.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "IMPOSTOS TOTAIS",
"pdf_tax_types_label": "Tipos de Impostos",
"pdf_expenses_label": "Despesas",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Cobrar a,",
"pdf_ship_to": "Envie a,",
"pdf_received_from": "Remetente:",

View File

@@ -652,6 +652,7 @@
"currency": "Moeda",
"contact": "Contato",
"category": "Categoria",
"uncategorized": "Uncategorized",
"from_date": "A partir da Data",
"to_date": "Até a Data",
"expense_date": "Data",
@@ -1326,7 +1327,8 @@
"finishing_update": "Acabando a Atualização",
"update_failed": "Atualização falhou",
"update_failed_text": "Desculpa! Sua atualização falhou no passo: {step}",
"update_warning": "Todos os arquivos do aplicativo e modelos padrão serão sobrescritos ao atualizar o aplicativo usando esta ferramenta. Faça backup de seus modelos e banco de dados antes de atualizar."
"update_warning": "Todos os arquivos do aplicativo e modelos padrão serão sobrescritos ao atualizar o aplicativo usando esta ferramenta. Faça backup de seus modelos e banco de dados antes de atualizar.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "IMPOSTOS TOTAIS",
"pdf_tax_types_label": "Tipos de Impostos",
"pdf_expenses_label": "Despesas",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Cobrar a,",
"pdf_ship_to": "Envie a,",
"pdf_received_from": "Remetente:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Валюта",
"contact": "Контакт",
"category": "Категория",
"uncategorized": "Uncategorized",
"from_date": "От даты",
"to_date": "До даты",
"expense_date": "Дата",
@@ -1326,7 +1327,8 @@
"finishing_update": "Заканчиваем обновление",
"update_failed": "Не удалось обновить",
"update_failed_text": "Извиняюсь! Ваше обновление не выполнено на шаге {step}",
"update_warning": "Все файлы приложения и файлы шаблонов по умолчанию будут перезаписаны при обновлении приложения с помощью этой утилиты. Перед обновлением сделайте резервную копию ваших шаблонов и базы данных."
"update_warning": "Все файлы приложения и файлы шаблонов по умолчанию будут перезаписаны при обновлении приложения с помощью этой утилиты. Перед обновлением сделайте резервную копию ваших шаблонов и базы данных.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Резервное копирование | Резервные копии",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "ВСЕГО НАЛОГОВ",
"pdf_tax_types_label": "Типы налогов",
"pdf_expenses_label": "Расходы",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Адрес счёта,",
"pdf_ship_to": "Адрес доставки,",
"pdf_received_from": "Получено от:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Kontakt",
"category": "Kategória",
"uncategorized": "Uncategorized",
"from_date": "Od dátumu",
"to_date": "Do dátumu",
"expense_date": "Dátum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Ukončovanie Aktualizácie",
"update_failed": "Aktualizácia zlyhala!",
"update_failed_text": "Aktualizácia zlyhala na : {step} kroku",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Záloha | Zálohy",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "Celkové dane",
"pdf_tax_types_label": "Typy daní",
"pdf_expenses_label": "Výdaje",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Odberateľ:",
"pdf_ship_to": "Doručiť do",
"pdf_received_from": "Prijaté od:",

View File

@@ -652,6 +652,7 @@
"currency": "Valuta",
"contact": "Pišite na",
"category": "Kategorija",
"uncategorized": "Uncategorized",
"from_date": "Od datuma",
"to_date": "Do danes",
"expense_date": "Datum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Posodobitev dodelave",
"update_failed": "Posodobitev ni uspela",
"update_failed_text": "Žal mi je! Posodobitev je bila neuspešna na : {step} koraku",
"update_warning": "Ko posodobite aplikacijo s tem orodjem, se prepišejo vse datoteke aplikacije in privzete datoteke predlog. Pred posodabljanjem naredite varnostno kopijo predlog in zbirke podatkov."
"update_warning": "Ko posodobite aplikacijo s tem orodjem, se prepišejo vse datoteke aplikacije in privzete datoteke predlog. Pred posodabljanjem naredite varnostno kopijo predlog in zbirke podatkov.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Varnostno kopiranje | Varnostne kopije",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "SKUPAJ DAVEK",
"pdf_tax_types_label": "Vrste davkov",
"pdf_expenses_label": "Odhodki",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Račun za,",
"pdf_ship_to": "Pošljite v,",
"pdf_received_from": "Prejeto od:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Kontakt",
"category": "Kategorija",
"uncategorized": "Uncategorized",
"from_date": "Datum od",
"to_date": "Datum do",
"expense_date": "Datum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Završavanje ažuriranja",
"update_failed": "Neuspešno ažuriranje",
"update_failed_text": "Žao mi je! Tvoje ažuriranje nije uspelo na koraku broj: {step} korak",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Bekap | Bekapi",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "UKUPNO POREZ",
"pdf_tax_types_label": "Tipovi Poreza",
"pdf_expenses_label": "Rashodi",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Račun za,",
"pdf_ship_to": "Isporučiti za,",
"pdf_received_from": "Poslat od strane:",

View File

@@ -652,6 +652,7 @@
"currency": "Valuta",
"contact": "Kontakt",
"category": "Kategori",
"uncategorized": "Uncategorized",
"from_date": "Från datum",
"to_date": "Till datum",
"expense_date": "Datum",
@@ -1326,7 +1327,8 @@
"finishing_update": "Avslutar uppdateringen",
"update_failed": "Uppdatering misslyckades",
"update_failed_text": "Uppdateringen misslyckades på steg : {step} step",
"update_warning": "Alla programfiler och standard mallfiler kommer att skrivas över när du uppdaterar programmet med det här verktyget. Ta en säkerhetskopia av dina mallar & databas innan du uppdaterar."
"update_warning": "Alla programfiler och standard mallfiler kommer att skrivas över när du uppdaterar programmet med det här verktyget. Ta en säkerhetskopia av dina mallar & databas innan du uppdaterar.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Säkerhetskopiering | Säkerhetskopieringar",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "SUMMA MOMS",
"pdf_tax_types_label": "Momssatser",
"pdf_expenses_label": "Utgifter",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Faktureras till,",
"pdf_ship_to": "Skickas till,",
"pdf_received_from": "Från:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "สกุลเงิน",
"contact": "ติดต่อเรา",
"category": "ประเภท",
"uncategorized": "Uncategorized",
"from_date": "จากวันที่",
"to_date": "ถึงวันที่",
"expense_date": "วันที่",
@@ -1326,7 +1327,8 @@
"finishing_update": "การอัพเดตเสร็จแล้ว",
"update_failed": "การอัพเดทล้มเหลว",
"update_failed_text": "โทษที!การอัปเดตของคุณล้มเหลวใน: ขั้นตอน {step}",
"update_warning": "ไฟล์แอปพลิเคชันและไฟล์แม่แบบเริ่มต้นทั้งหมดจะถูกเขียนทับเมื่อคุณอัปเดตแอปพลิเคชันโดยใช้ยูทิลิตีนี้โปรดใช้การสำรองข้อมูลของแม่แบบและฐานข้อมูลของคุณก่อนที่จะอัพเดต"
"update_warning": "ไฟล์แอปพลิเคชันและไฟล์แม่แบบเริ่มต้นทั้งหมดจะถูกเขียนทับเมื่อคุณอัปเดตแอปพลิเคชันโดยใช้ยูทิลิตีนี้โปรดใช้การสำรองข้อมูลของแม่แบบและฐานข้อมูลของคุณก่อนที่จะอัพเดต",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "การสำรองข้อมูล | ข้อมูลสำรอง",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "ภาษีทั้งหมด",
"pdf_tax_types_label": "ประเภทภาษี",
"pdf_expenses_label": "ค่าใช้จ่าย",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "ที่อยู่เรียกเก็บเงิน,",
"pdf_ship_to": "ที่อยู่สำหรับจัดส่ง,",
"pdf_received_from": "ได้รับจาก:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "İletişim",
"category": "Kategori",
"uncategorized": "Uncategorized",
"from_date": "Başlangıç tarihi",
"to_date": "Bitiş tarihi",
"expense_date": "Tarih",
@@ -1326,7 +1327,8 @@
"finishing_update": "Güncelleme tamamlanıyor",
"update_failed": "Güncelleştirme Başarısız",
"update_failed_text": "Üzgünüz! Güncelleştirmeniz :{step} adımında başarısız oldu",
"update_warning": "Uygulamayı bu araçla güncellediğinizde tüm uygulama dosyaları ve varsayılan şablon dosyaları üzerine yazılacaktır. Güncellemeden önce şablonlarınızın ve veritabanınızın yedeğini almayı unutmayın."
"update_warning": "Uygulamayı bu araçla güncellediğinizde tüm uygulama dosyaları ve varsayılan şablon dosyaları üzerine yazılacaktır. Güncellemeden önce şablonlarınızın ve veritabanınızın yedeğini almayı unutmayın.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Yedek | Yedekler",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOPLAM VERGİ",
"pdf_tax_types_label": "Vergi Türleri",
"pdf_expenses_label": "Giderler",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Fatura Adresi,",
"pdf_ship_to": "Teslimat Adresi,",
"pdf_received_from": "Alındığı Kişi:",

View File

@@ -652,6 +652,7 @@
"currency": "Валюта",
"contact": "Контакт",
"category": "Категорія",
"uncategorized": "Uncategorized",
"from_date": "Від дати",
"to_date": "До дати",
"expense_date": "Дата",
@@ -1326,7 +1327,8 @@
"finishing_update": "Оновлення завершення",
"update_failed": "Спроба оновлення зазнала невдачі",
"update_failed_text": "Вибачте! Оновлення не вдалось на кроці: {step} ",
"update_warning": "Всі файли програми та файли шаблонів за замовчуванням будуть перезаписані, коли ви оновите програму за допомогою цієї утиліти. Будь ласка, зробіть резервну копію ваших шаблонів і бази даних перед оновленням."
"update_warning": "Всі файли програми та файли шаблонів за замовчуванням будуть перезаписані, коли ви оновите програму за допомогою цієї утиліти. Будь ласка, зробіть резервну копію ваших шаблонів і бази даних перед оновленням.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Резервне копіювання | Резервні копії",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "Загальний звіт податків",
"pdf_tax_types_label": "Типи податків",
"pdf_expenses_label": "Витрати",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Рахунок до,",
"pdf_ship_to": "Доставити до,",
"pdf_received_from": "Отримано від:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "Tiền tệ",
"contact": "Tiếp xúc",
"category": "Danh mục",
"uncategorized": "Uncategorized",
"from_date": "Từ ngày",
"to_date": "Đến nay",
"expense_date": "Ngày",
@@ -1326,7 +1327,8 @@
"finishing_update": "Cập nhật kết thúc",
"update_failed": "Cập nhật không thành công",
"update_failed_text": "Lấy làm tiếc! Cập nhật của bạn không thành công vào: bước {step}",
"update_warning": "Tất cả các tệp ứng dụng và tệp mẫu mặc định sẽ bị ghi đè khi bạn cập nhật ứng dụng bằng công cụ này. Vui lòng sao lưu các mẫu và cơ sở dữ liệu của bạn trước khi thực hiện cập nhật."
"update_warning": "Tất cả các tệp ứng dụng và tệp mẫu mặc định sẽ bị ghi đè khi bạn cập nhật ứng dụng bằng công cụ này. Vui lòng sao lưu các mẫu và cơ sở dữ liệu của bạn trước khi thực hiện cập nhật.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Sao lưu | Sao lưu",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TỔNG THUẾ",
"pdf_tax_types_label": "Các loại thuế",
"pdf_expenses_label": "Chi phí",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Hoa đơn để,",
"pdf_ship_to": "Tàu,",
"pdf_received_from": "Nhận được tư:",

View File

@@ -652,6 +652,7 @@
"currency": "Currency",
"contact": "Contact",
"category": "Category",
"uncategorized": "Uncategorized",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
@@ -1326,7 +1327,8 @@
"finishing_update": "Finishing Update",
"update_failed": "Update Failed",
"update_failed_text": "Sorry! Your update failed on : {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "Backup | Backups",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "TOTAL TAX",
"pdf_tax_types_label": "Tax Types",
"pdf_expenses_label": "Expenses",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",

View File

@@ -652,6 +652,7 @@
"currency": "主要貨幣",
"contact": "聯絡",
"category": "分類",
"uncategorized": "Uncategorized",
"from_date": "啟始日",
"to_date": "終止日",
"expense_date": "日期",
@@ -1326,7 +1327,8 @@
"finishing_update": "正完成更新",
"update_failed": "更新失敗",
"update_failed_text": "抱歉! 你的更新在這步驟中失敗: {step} step",
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating.",
"requirements_not_met": "Update cannot continue because some system requirements are not met (including minimum PHP version). Please fix the failed requirements and try again."
},
"backup": {
"title": "備份 | 備份",
@@ -1648,6 +1650,7 @@
"pdf_total_tax_label": "稅項總額",
"pdf_tax_types_label": "稅收類型",
"pdf_expenses_label": "支出",
"pdf_expense_group_total_label": "Group total:",
"pdf_bill_to": "帳單地址,",
"pdf_ship_to": "送貨地址,",
"pdf_received_from": "接收自",

View File

@@ -1,64 +1,61 @@
{
"private": true,
"engines": {
"node": ">=24"
},
"type": "module",
"scripts": {
"dev": "vite",
"watch": "vite build --watch",
"build": "vite build",
"serve": "vite preview",
"test": "eslint ./resources/scripts --ext .js,.vue"
"test": "eslint ./resources/scripts"
},
"devDependencies": {
"@rvxlab/tailwind-plugin-ios-full-height": "^1.1.0",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"@vitejs/plugin-vue": "^5.2.1",
"@tailwindcss/vite": "^4.0.0",
"@vitejs/plugin-vue": "^6.0.0",
"@vue/compiler-sfc": "^3.5.13",
"autoprefixer": "^10.4.20",
"cross-env": "^7.0.3",
"eslint": "^9.18.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-vue": "^9.32.0",
"postcss": "^8.4.49",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-vue": "^10.0.0",
"prettier": "^3.4.2",
"sass": "^1.83.1",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.17"
"tailwind-scrollbar": "^4.0.0",
"tailwindcss": "^4.0.0"
},
"dependencies": {
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.2.0",
"@popperjs/core": "^2.11.8",
"@stripe/stripe-js": "^2.4.0",
"@tiptap/core": "^2.11.2",
"@tiptap/extension-link": "^2.11.2",
"@tiptap/extension-text-align": "^2.11.2",
"@tiptap/pm": "^2.11.2",
"@tiptap/starter-kit": "^2.11.2",
"@tiptap/vue-3": "^2.11.2",
"@types/node": "^20.11.9",
"@tiptap/core": "^3.0.0",
"@tiptap/extension-text-align": "^3.0.0",
"@tiptap/pm": "^3.0.0",
"@tiptap/starter-kit": "^3.0.0",
"@tiptap/vue-3": "^3.0.0",
"@types/node": "^24.0.0",
"@vuelidate/components": "^1.2.6",
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
"@vueuse/core": "^12.4.0",
"axios": "0.30.0",
"chart.js": "^2.9.4",
"@vueuse/core": "^14.0.0",
"axios": "1.14.0",
"chart.js": "^4.5.1",
"guid": "^0.0.12",
"laravel-vite-plugin": "^1.1.1",
"laravel-vite-plugin": "^3.0.0",
"lodash": "^4.17.21",
"maska": "^3.0.4",
"mini-svg-data-uri": "^1.4.4",
"moment": "^2.30.1",
"path": "^0.12.7",
"pinia": "^2.3.0",
"pinia": "^3.0.0",
"v-money3": "^3.24.1",
"v-tooltip": "^4.0.0-beta.17",
"vite": "^6.0.7",
"vite": "^8.0.0",
"vue": "^3.5",
"vue-flatpickr-component": "^11.0.5",
"vue-flatpickr-component": "^12.0.0",
"vue-i18n": "^11.0.1",
"vue-router": "^4.5.0",
"vue-router": "^5.0.0",
"vuedraggable": "^4.1.0"
}
}
}

View File

@@ -1,7 +0,0 @@
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

Some files were not shown because too many files have changed in this diff Show More