Compare commits

...

165 Commits
2.0.1 ... 3.0.0

Author SHA1 Message Date
06a538bb81 Merge branch 'build-version300' into 'master'
Build version300

See merge request mohit.panjvani/crater-web!162
2020-01-27 09:26:58 +00:00
7ab0419f27 build version300 2020-01-27 14:47:45 +05:30
a7275aaa42 fix report download & payments delete issue 2020-01-27 14:46:40 +05:30
bc4e6a05ea fix Surround DB_PASSWORD with quotes #104 issue 2020-01-27 14:22:21 +05:30
ca170f5a87 fix dashbord & using FROM_MAIL_ADDRESS issues 2020-01-27 13:43:48 +05:30
22e7e96dfa fix new lines in address field issue 2020-01-27 11:57:47 +05:30
fcfd1ddb7a build 300 2020-01-27 11:19:22 +05:30
daf8c9265b fix tab & language issue 2020-01-27 11:18:11 +05:30
824d2e3e8d update app version 2020-01-26 12:32:57 +05:30
3cd975dbbd new build 2020-01-25 13:33:50 +05:30
8e50c36a71 Merge branch 'master' 2020-01-25 13:12:39 +05:30
b499741ab4 change button style of primary actions on view pages 2020-01-25 13:12:20 +05:30
b409cdb913 Merge branch 'auto-update' into 'master'
fix auto update issue in dev

See merge request mohit.panjvani/crater-web!160
2020-01-22 16:10:36 +00:00
13e56105e3 fix auto update issue in dev 2020-01-22 13:39:59 +05:30
da996c1f33 Merge branch 'master' of https://github.com/bytefury/crater 2020-01-19 11:49:35 +05:30
bb6fb2f49d Merge pull request #131 from jjoseba/master
Spanish corrections
2020-01-08 15:39:16 +05:30
400296575e Updated Spanish translation 2020-01-08 10:58:26 +01:00
d58c790b1f Merge branch 'build-300' into 'master'
fix mailgun config issue & build 300

See merge request mohit.panjvani/crater-web!153
2020-01-07 08:32:04 +00:00
c674c2ab9e build verison 300 2020-01-07 13:10:55 +05:30
d79692cf3b mail configuration issue 2020-01-07 12:33:03 +05:30
0176a854b8 Merge branch 'refactor-master' into 'master'
refactor payment view and mutation

See merge request mohit.panjvani/crater-web!151
2020-01-06 16:08:53 +00:00
00548ea908 refactor payment view 2020-01-06 19:03:08 +05:30
09e335a8a7 fix conflicts 2020-01-06 14:48:08 +05:30
53e2ed253f Merge branch 'master' 2020-01-06 14:47:06 +05:30
06b035d9ac Merge branch 'build-300' into 'master'
fix payment issue & build version 300

See merge request mohit.panjvani/crater-web!150
2020-01-06 09:16:49 +00:00
5c88cbcc42 Merge branch 'master' 2020-01-06 14:45:09 +05:30
d9b175a676 fix payment issue & build version 300 2020-01-06 14:08:29 +05:30
f5b9bc95c6 Merge branch 'build-300' into 'master'
build version 300

See merge request mohit.panjvani/crater-web!149
2020-01-06 06:47:08 +00:00
586dcdea0d build version 300 2020-01-06 12:02:12 +05:30
50957fc179 Merge pull request #127 from hypnodev/typo-fix-crop-popup
Typo fix crop popup
2020-01-05 23:41:51 +05:30
c725e4744b Compiled assets 2020-01-05 19:00:29 +01:00
7479ce237e Typo fix #126 2020-01-05 18:57:46 +01:00
84420441c0 Merge pull request #2 from bytefury/master
Merge pull request #2 from bytefury/master
2020-01-05 14:03:26 +01:00
ac96721e87 build 220 2020-01-05 13:50:08 +05:30
db4c7f5e32 fix merge conflicts 2020-01-05 13:45:10 +05:30
87dc78eea0 Merge pull request #115 from hypnodev/add-available-lang-to-onboarding
Added available languages to Onboarding
2020-01-05 13:39:02 +05:30
e9c2898056 Merge pull request #119 from hypnodev/fix-http-mixed-request
Fix http mixed request
2020-01-05 13:37:27 +05:30
b9c4570137 Merge pull request #121 from MakerLab-Dev/translations-updates
Translations Updates
2020-01-05 13:35:01 +05:30
8e2525cc6c new build 220 2020-01-05 13:34:01 +05:30
8862a93f23 fix border-left jump on active selection 2020-01-05 13:08:42 +05:30
82efd88920 Merge branch 'sidebar-view' into 'master'
sidebar-view modified

See merge request mohit.panjvani/crater-web!132
2020-01-05 07:24:12 +00:00
0ef528d296 Merge branch 'payment_receipt' into 'master' 2020-01-05 07:22:36 +00:00
4c33a5d88c Fix Invoice/Estimate template issues and Add Payment Receipt, Custom Payment Modes and Item units 2020-01-05 07:22:36 +00:00
d64d06181b Translations Updates
Spanish translation: 100%
Removed a blank space in English translation
Changed the copyright year to 2020 in all translations
2020-01-03 17:21:43 +01:00
ef9cf2db22 Fix mixed content when use endpoint for categories list 2020-01-03 00:14:05 +01:00
96c295a003 Added available languages to Onboarding 2019-12-31 10:20:13 +01:00
22528f5b66 Merge pull request #1 from bytefury/master
Same as bytefury/crater
2019-12-31 10:15:17 +01:00
1cd9c72537 Merge pull request #108 from hypnodev/fix-postgresql-case-sensitiive-bug
Fix case sensitive PostgreSQL bug
2019-12-31 09:26:46 +05:30
7253b43eb4 Fix case sensitive PostgreSQL bug 2019-12-29 14:50:03 +01:00
181964cf03 Merge pull request #105 from PHClement/patch-1
Update fr.json
2019-12-28 21:13:42 +05:30
5914245ae4 Merge pull request #106 from cilas/feature/translate-app-to-portuguese
Feature/translate app to portuguese
2019-12-28 21:11:32 +05:30
1bf3d28d4e Update fr.json
Correct some mistake, please approve it, thank you ;)
2019-12-28 01:45:25 +01:00
dbcbd93ace Translate to Brazilian Portuguese Complete 2019-12-27 21:45:15 -03:00
1729c6a308 Translated partial wizard section 2019-12-27 17:42:54 -03:00
019493cbfa Translated settings section 2019-12-27 15:55:34 -03:00
60540ba966 Translated reports section 2019-12-27 13:14:53 -03:00
601ad419ec Translated login section 2019-12-27 12:54:21 -03:00
80e7bab891 Translated expenses section 2019-12-27 12:50:37 -03:00
f5c8befbf0 Translated payments section 2019-12-27 12:33:56 -03:00
09c984baa7 Translated credit_notes section 2019-12-27 12:27:42 -03:00
0d93260672 Translated invoice section 2019-12-27 12:24:59 -03:00
3e9e217f92 Translate estimate session 2019-12-27 00:53:16 -03:00
3cd8859c62 add Brazilian Portuguese language to CompanyController 2019-12-27 00:14:57 -03:00
4493b4a419 add language pt_BR to plugins 2019-12-27 00:11:41 -03:00
79e3e70bd6 add pt_BR language option 2019-12-26 22:47:09 -03:00
56a955befd delete yarnlock file 2019-12-25 19:29:22 +05:30
496c28f80d remove transifex from readme 2019-12-25 19:27:41 +05:30
7a59f3fe0c refactor variable in estimate view scss 2019-12-23 21:05:48 +05:30
3d6875a532 refactor css variables 2019-12-23 21:00:26 +05:30
15bf380f4f Merge pull request #93 from surajjdhv/master
Fixed incorrectly named language (ar.json) file
2019-12-23 12:54:04 +05:30
0b910db039 Fixed incorrectly named language (ar.json) file 2019-12-22 21:47:30 +05:30
0e5e8f602f update error message for db file permission issue 2019-12-21 23:02:05 +05:30
d9db0f9401 Merge pull request #80 from eboye/master
Add Serbian Dinar currency
2019-12-21 14:08:10 +05:30
c0da7c7339 Merge pull request #89 from claretnnamocha/master
Docs
2019-12-20 19:15:16 +05:30
7e7599b4a7 Merge branch 'master' into master 2019-12-20 09:35:03 +01:00
99cd88e6c6 Revert "Update CompanyController.php"
This reverts commit 053a06229c.
2019-12-20 09:32:29 +01:00
053a06229c Update CompanyController.php 2019-12-20 09:30:15 +01:00
1a6e8280a8 update readme 2019-12-18 20:58:44 +05:30
125e8be83c Merge pull request #87 from hsnapps/master
Added the Arabic language localization
2019-12-18 20:56:06 +05:30
4d89ca2101 Added the Arabic language localization 2019-12-18 10:18:04 +03:00
e8aee3bb32 Add Serbian Dinar currency 2019-12-17 11:32:58 +01:00
d3c7ca75f0 Documenting web routes 2019-12-16 20:41:59 +01:00
694d5f56d5 Documenting Controllers 2019-12-16 20:17:43 +01:00
a48439785c Merge pull request #68 from BirkhoffLee/master
Docker: fix update functionality
2019-12-14 21:23:24 +05:30
7c9bd84f00 Docker: fix update functionality
Added php zip extension
2019-12-14 15:43:01 +00:00
bd5a93d81c Merge branch 'master' of https://github.com/bytefury/crater 2019-12-14 19:56:24 +05:30
858e10953b fix grammar 2019-12-14 19:13:59 +05:30
3617032735 Merge branch 'build210' into 'master'
fix installation issue & build 210

See merge request mohit.panjvani/crater-web!143
2019-12-14 13:27:26 +00:00
75ddc51b1e fix installation issue & build 210 2019-12-14 18:50:13 +05:30
1dfa36e396 Merge branch 'build210' into 'master'
fix estimate & invoice tax issue

See merge request mohit.panjvani/crater-web!142
2019-12-14 13:06:38 +00:00
d9e9a5a540 fix estimate & invoice tax issue 2019-12-14 18:29:46 +05:30
ea6e11c324 Merge branch 'build210' into 'master'
fix version update issue

See merge request mohit.panjvani/crater-web!141
2019-12-14 12:48:37 +00:00
f55dfe0b46 fix version update issue 2019-12-14 17:12:47 +05:30
3eac3b8af5 Merge branch 'build210' into 'master'
fix auto auto generate issue & build210

See merge request mohit.panjvani/crater-web!140
2019-12-14 11:20:01 +00:00
2b2bd4351a fix auto auto generate issue & build210 2019-12-14 15:45:26 +05:30
b9c32bbdc1 Merge branch 'build-version210' into 'master'
Build version210

See merge request mohit.panjvani/crater-web!139
2019-12-14 09:49:21 +00:00
bceffbf6a0 build version210 2019-12-14 14:43:55 +05:30
7c6a40374d fix tax percent & pdf money format issue 2019-12-14 14:42:34 +05:30
d04e142a3e build version210 2019-12-14 13:59:59 +05:30
f11436736b add settings use in Update listener 2019-12-14 13:57:18 +05:30
9271ceba45 Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into build-version210 2019-12-14 13:55:26 +05:30
c88eb24265 fix pdf & installation issue 2019-12-14 13:54:35 +05:30
5eb0a04378 Update issue templates 2019-12-14 13:03:42 +05:30
d926073095 add ios link to readme 2019-12-14 12:55:08 +05:30
a691969025 Merge branch 'master' of https://github.com/bytefury/crater 2019-12-14 12:35:40 +05:30
7df06fb005 fix invoice number validation 2019-12-14 12:35:32 +05:30
45db850025 Merge pull request #59 from vkiranmaniya/master
Removed JSON SQL datatype, Replaced with TEXT Type
2019-12-14 12:32:31 +05:30
18a50315ba Removed json SQL datatype, Replaced with text
The JSON SQL datatype is not supported in some of SQL server(i.e. 5.6.44). Replaced it with text datatype.
2019-12-13 17:24:07 +05:30
bce1b4bb3e build 210 2019-12-13 17:03:55 +05:30
ddd204105f fix installation issue 2019-12-13 17:03:44 +05:30
e030d4b9d0 Merge branch 'build-210' into 'master'
build version210

See merge request mohit.panjvani/crater-web!138
2019-12-13 10:48:54 +00:00
302968225a build version210 2019-12-13 15:22:37 +05:30
e59bf288ce Merge branch 'pdf-issues' into 'master'
Fix PDF issues

See merge request mohit.panjvani/crater-web!137
2019-12-13 09:43:32 +00:00
b1fcd90b62 refactor format_money_pdf helpers 2019-12-13 14:40:17 +05:30
ddb0ff1b8a fix pdf currency display issue 2019-12-13 14:34:21 +05:30
ce99fa3d82 Fix PDF issues 2019-12-13 13:31:26 +05:30
e28c89085d Merge branch 'master' 2019-12-12 20:42:17 +05:30
34f7e33abc Merge branch 'master' of https://github.com/bytefury/crater 2019-12-12 20:31:57 +05:30
80be7a492d Merge pull request #50 from nhedger/master
Add missing currency code to customer create/edit form
2019-12-12 20:27:45 +05:30
387cb4490d Merge branch 'add-customization' into 'master'
update invoice, estimate & payment vars

See merge request mohit.panjvani/crater-web!135
2019-12-12 14:56:10 +00:00
09829a559e Merge branch 'pdf-issue' into 'master'
fix Pdf issue

See merge request mohit.panjvani/crater-web!136
2019-12-12 14:55:04 +00:00
b06fc5f0b9 Add missing currency code to customer create form 2019-12-12 14:37:16 +01:00
5f7401f622 update invoice, estimate & payment vars 2019-12-12 16:04:12 +05:30
4f6dae919b Merge branch 'add-customization' into 'master'
Add customization

See merge request mohit.panjvani/crater-web!134
2019-12-12 10:05:16 +00:00
36be395579 Remove unwanted code 2019-12-12 14:59:54 +05:30
79e77f9e16 fix pdf lang issue 2019-12-12 14:20:31 +05:30
cbf0af2120 Refactor Customization Page 2019-12-12 13:46:09 +05:30
92f754e888 Merge pull request #43 from nhedger/master
Prepend currency code to label to allow searching by currency code
2019-12-12 13:25:21 +05:30
a6896eaa01 Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into pdf-issue 2019-12-12 13:17:52 +05:30
01f3646869 add meta tag 2019-12-12 11:50:25 +05:30
b2918e9dbb Merge pull request #44 from JaxWilko/fix-incorrect-headers-sent
Removed a space that forced apache to send the wrong headers
2019-12-12 08:59:00 +05:30
0a064ec5ba Removed a space that forced apache to send the wrong headers 2019-12-12 00:50:45 +00:00
5f0b4b3496 Prepend currency code to selector label. 2019-12-11 20:36:46 +01:00
17b59f0d19 Merge branch 'master' 2019-12-11 20:16:23 +05:30
283b910cc3 remove state & city routes from api.php and fix cancel spelling mistake 2019-12-11 20:16:11 +05:30
81739827c0 Add customization 2019-12-11 17:02:28 +05:30
90edc3a85e Merge branch 'dashboard-initial-loading' into 'master'
refactor initial data loading in dashboard

See merge request mohit.panjvani/crater-web!133
2019-12-11 10:18:58 +00:00
655c2a7849 Merge branch 'master' of https://github.com/bytefury/crater 2019-12-11 13:35:32 +05:30
ca833d174e update readme 2019-12-11 13:35:13 +05:30
33e8381fc4 Merge pull request #8 from BirkhoffLee/master
Initial Docker support
2019-12-11 13:04:43 +05:30
9b5125d440 Merge branch 'master' of https://github.com/bytefury/crater 2019-12-11 12:45:03 +08:00
2899021804 Update example env in accordance w/ Docker setup 2019-12-10 23:53:28 +08:00
d8f6d03d1e Docker: rename nginx container name 2019-12-10 23:52:23 +08:00
c474e98925 Docker: copy example env file when building 2019-12-10 23:40:59 +08:00
799d212d9b refactor classes on invoice and estimate view page 2019-12-10 11:15:49 +05:30
9424dc6c27 refactor initial data loading in dashboard 2019-12-09 19:27:21 +05:30
fa15502ce7 refactor primary color-var 2019-12-09 19:20:11 +05:30
1f4d3bf784 sidebar-view modified 2019-12-09 18:58:53 +05:30
3692373cd2 Docker: switch from passport:install to passport:keys during build 2019-12-09 19:25:57 +08:00
7bba576dca Merge branch 'build-202' into 'master'
build version-202

See merge request mohit.panjvani/crater-web!130
2019-12-09 07:00:58 +00:00
05454af593 build version-202 2019-12-09 12:03:57 +05:30
74fe481ed5 Merge branch 'fix-view-issue' into 'master'
fix invoice & estimate view issue

See merge request mohit.panjvani/crater-web!129
2019-12-09 05:59:44 +00:00
1cd654b0cc fix invoice & estimate view issue 2019-12-09 11:19:57 +05:30
0c71356f59 Docker: remove migration instruction 2019-12-04 18:31:06 +08:00
e539bb501d Docker: persistant database storage in example docker-compose.yaml 2019-12-04 17:22:59 +08:00
2fcd169270 Downgrade Docker image php version to 7.3.12 2019-12-04 17:19:16 +08:00
14d71fedb3 Rename docker-compose.yml.example -> docker-compose.yaml.example 2019-12-04 14:54:28 +08:00
7fe9a4c2a2 Fix Dockerfile and docker-compose.yml
1. Generate a testing SQLite db on build
2. Optimize image layer caching
3. Fix permissions
4. Simplify nginx configuration
5. Fix nginx infinite redirect loop (couldn't access app folder)
2019-12-04 14:49:57 +08:00
7b697a477e Fix MariaDB config in Docker compose
by specifying a root password.
2019-12-04 11:20:50 +08:00
146cf835b9 Fix composer install in Dockerfile 2019-12-04 08:59:01 +08:00
ec87e72547 Add .dockerignore file
This excludes unnecessary files for production use on Docker image
build.
2019-12-04 08:26:31 +08:00
bf2e8c9c99 Use multi-stage build for Docker image
1. Allows to build the composer dependencies with official composer img
2. php-fpm --nodaemonize: Force to stay in foreground and ignore daemo-
   nize option from configuration file
2019-12-04 08:23:11 +08:00
b6096aadfa Add MariaDB to docker-compose example
1. Gives an example set up of a MySQL database in docker-compose
2. `php` now depends on `db`, and `nginx` depends on `php`. This
ensures the integrity of the stack.
2019-12-03 21:31:56 +08:00
1cbc41c3ce Simplify docker-ext-install in Dockerfile 2019-12-03 20:24:54 +08:00
8bc5ea2d5e Initial Docker support
This commit adds:
1. A Dockerfile that runs PHP 7.2 FPM on Alpine Linux
2. A example docker-compose file that simplifies deployment
2019-11-21 12:54:22 +08:00
184 changed files with 9395 additions and 9485 deletions

10
.dockerignore Normal file
View File

@ -0,0 +1,10 @@
.dockerignore
.gitignore
*.md
.git/
.idea/
.DS_Store/
docker-compose.*
LICENSE
nginx.conf
yarn.lock

View File

@ -1,15 +1,15 @@
APP_ENV=production
APP_KEY=base64:kgk/4DW1vEVy7aEvet5FPp5un6PIGe/so8H0mvoUtW0=
APP_DEBUG=false
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://crater.test
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_HOST=db
DB_PORT=3306
DB_DATABASE=crater
DB_USERNAME=root
DB_PASSWORD=bytefury
DB_USERNAME=crater
DB_PASSWORD="crater"
BROADCAST_DRIVER=log
CACHE_DRIVER=file

26
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,26 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Please complete the following information:**
- Crater version:
- PHP version:
- Database type and version:
**Optional info**
- OS: [e.g. Ubuntu]
- Browser: [e.g. chrome, safari]

View File

@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

2
.gitignore vendored
View File

@ -11,3 +11,5 @@ Homestead.yaml
.rnd
/.expo
/.vscode
docker-compose.yml
docker-compose.yaml

52
Dockerfile Normal file
View File

@ -0,0 +1,52 @@
##### STAGE 1 #####
FROM composer as composer
# Copy composer files from project root into composer container's working dir
COPY composer.* /app/
# Copy database directory for autoloader optimization
COPY database /app/database
# Run composer to build dependencies in vendor folder
RUN composer install --no-scripts --no-suggest --no-interaction --prefer-dist --optimize-autoloader
# Copy everything from project root into composer container's working dir
COPY . /app
RUN composer dump-autoload --optimize --classmap-authoritative
##### STAGE 2 #####
FROM php:7.3.12-fpm-alpine
# Use the default production configuration
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
RUN apk add --no-cache libpng-dev libxml2-dev oniguruma-dev libzip-dev && \
docker-php-ext-install bcmath ctype json gd mbstring pdo pdo_mysql tokenizer xml zip
# Set container's working dir
WORKDIR /app
# Copy everything from project root into php container's working dir
COPY . /app
# Copy vendor folder from composer container into php container
COPY --from=composer /app/vendor /app/vendor
RUN touch database/database.sqlite && \
cp .env.example .env && \
php artisan config:cache && \
php artisan passport:keys && \
php artisan key:generate && \
chown -R www-data:www-data . && \
chmod -R 755 . && \
chmod -R 775 storage/framework/ && \
chmod -R 775 storage/logs/ && \
chmod -R 775 bootstrap/cache/
EXPOSE 9000
CMD ["php-fpm", "--nodaemonize"]

View File

@ -7,8 +7,8 @@ use Crater\Country;
class Address extends Model
{
const BILLING_TYPE = 'BILLING';
const SHIPPING_TYPE = 'SHIPPING';
const BILLING_TYPE = 'billing';
const SHIPPING_TYPE = 'shipping';
protected $fillable = [
'name',

View File

@ -0,0 +1,51 @@
<?php
namespace Crater\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Filesystem\Filesystem;
class ResetApp extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'reset:app';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Clean database, database_created and public/storage folder';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if ($this->confirm('Do you wish to continue? This will delete your tables')) {
Artisan::call('migrate:reset --force');
\Storage::disk('local')->delete('database_created');
// $file = new Filesystem;
// $file->cleanDirectory('public/storage');
}
}
}

View File

@ -12,7 +12,7 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
Commands\ResetApp::class
];
/**

View File

@ -49,15 +49,20 @@ class Estimate extends Model
];
protected $casts = [
'total' => 'float',
'tax' => 'float',
'sub_total' => 'float'
'total' => 'integer',
'tax' => 'integer',
'sub_total' => 'integer',
'discount' => 'float',
'discount_val' => 'integer',
];
public static function getNextEstimateNumber()
public static function getNextEstimateNumber($value)
{
// Get the last created order
$lastOrder = Estimate::orderBy('created_at', 'desc')->first();
// Get the last created order
$lastOrder = Estimate::where('estimate_number', 'LIKE', $value . '-%')
->orderBy('created_at', 'desc')
->first();
if (!$lastOrder) {
// We get here if there is no order at all
// If there is no number set it to 0, which will be 1 at the end.
@ -99,10 +104,16 @@ class Estimate extends Model
public function getEstimateNumAttribute()
{
$position = $this->strposX($this->estimate_number, "-", 2) + 1;
$position = $this->strposX($this->estimate_number, "-", 1) + 1;
return substr($this->estimate_number, $position);
}
public function getEstimatePrefixAttribute()
{
$prefix = explode("-",$this->estimate_number)[0];
return $prefix;
}
private function strposX($haystack, $needle, $number)
{
if ($number == '1') {

View File

@ -20,11 +20,22 @@ use Crater\CompanySetting;
class CompanyController extends Controller
{
/**
* Retrive the Admin account.
* @return \Crater\User
*/
public function getAdmin()
{
return User::find(1);
}
/**
* Update the Admin profile.
* Includes name, email and (or) password
*
* @param \Crater\Http\Requests\ProfileRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function updateAdminProfile(ProfileRequest $request)
{
$verifyEmail = User::where('email', $request->email)->first();
@ -54,6 +65,14 @@ class CompanyController extends Controller
]);
}
/**
* Get Admin Account alongside the country from the addresses table and
* The company from companies table
*
* @return \Illuminate\Http\JsonResponse
*/
public function getAdminCompany()
{
$user = User::with(['addresses', 'addresses.country', 'company'])->find(1);
@ -63,6 +82,13 @@ class CompanyController extends Controller
]);
}
/**
* Update Admin Company Details
* @param \Crater\Http\Requests\CompanyRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function updateAdminCompany(CompanyRequest $request)
{
$user = User::find(1);
@ -85,6 +111,11 @@ class CompanyController extends Controller
]);
}
/**
* Retrieve General App Settings
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getGeneralSettings(Request $request)
{
$date_formats = DateFormatter::get_list();
@ -115,7 +146,10 @@ class CompanyController extends Controller
$languages = [
["code"=>"en", "name" => "English"],
["code"=>"fr", "name" => "French"],
["code"=>"es", "name" => "Spanish"]
["code"=>"es", "name" => "Spanish"],
["code"=>"ar", "name" => "العربية"],
["code"=>"de", "name" => "German"],
["code"=>"pt_BR", "name" => "Brazilian Portuguese"],
];
return response()->json([
@ -133,6 +167,13 @@ class CompanyController extends Controller
]);
}
/**
* Update General App Settings
* @param \Crater\Http\Requests\CompanySettingRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function updateGeneralSettings(CompanySettingRequest $request)
{
$sets = [
@ -153,6 +194,63 @@ class CompanyController extends Controller
]);
}
public function getCustomizeSetting (Request $request)
{
$invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company'));
$invoice_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company'));
$estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company'));
$estimate_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company'));
$payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company'));
$payment_auto_generate = CompanySetting::getSetting('payment_auto_generate', $request->header('company'));
return response()->json([
'invoice_prefix' => $invoice_prefix,
'invoice_auto_generate' => $invoice_auto_generate,
'estimate_prefix' => $estimate_prefix,
'estimate_auto_generate' => $estimate_auto_generate,
'payment_prefix' => $payment_prefix,
'payment_auto_generate' => $payment_auto_generate,
]);
}
public function updateCustomizeSetting (Request $request)
{
$sets = [];
if ($request->type == "PAYMENTS") {
$sets = [
'payment_prefix'
];
}
if ($request->type == "INVOICES") {
$sets = [
'invoice_prefix',
];
}
if ($request->type == "ESTIMATES") {
$sets = [
'estimate_prefix',
];
}
foreach ($sets as $key) {
CompanySetting::setSetting($key, $request->$key, $request->header('company'));
}
return response()->json([
'success' => true
]);
}
/**
* Update a specific Company Setting
* @param \Crater\Http\Requests\SettingRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function updateSetting(SettingRequest $request)
{
CompanySetting::setSetting($request->key, $request->value, $request->header('company'));
@ -162,6 +260,11 @@ class CompanyController extends Controller
]);
}
/**
* Retrieve Specific Company Setting
* @param \Crater\Http\Requests\SettingKeyRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function getSetting(SettingKeyRequest $request)
{
$setting = CompanySetting::getSetting($request->key, $request->header('company'));
@ -171,6 +274,12 @@ class CompanyController extends Controller
]);
}
/**
* Retrieve App Colors
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getColors(Request $request)
{
$colors = [
@ -205,7 +314,7 @@ class CompanyController extends Controller
* Upload the company logo to storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function uploadCompanyLogo(Request $request)
{
@ -232,7 +341,7 @@ class CompanyController extends Controller
* Upload the Admin Avatar to public storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function uploadAdminAvatar(Request $request)
{

View File

@ -19,7 +19,7 @@ class CustomersController extends Controller
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
@ -53,7 +53,7 @@ class CustomersController extends Controller
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function store(Requests\CustomerRequest $request)
{
@ -104,7 +104,7 @@ class CustomersController extends Controller
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function show($id)
{
@ -124,7 +124,7 @@ class CustomersController extends Controller
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function edit($id)
{
@ -144,7 +144,7 @@ class CustomersController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function update($id, Requests\CustomerRequest $request)
{
@ -177,6 +177,7 @@ class CustomersController extends Controller
$customer->enable_portal = $request->enable_portal;
$customer->save();
$customer->addresses()->delete();
if ($request->addresses) {
foreach ($request->addresses as $address) {
$newAddress = $customer->addresses()->firstOrNew(['type' => $address["type"]]);
@ -203,10 +204,10 @@ class CustomersController extends Controller
}
/**
* Remove the specified resource from storage.
* Remove the specified Customer along side all his/her resources (ie. Estimates, Invoices, Payments and Addresses)
*
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function destroy($id)
{
@ -217,6 +218,13 @@ class CustomersController extends Controller
]);
}
/**
* Remove a list of Customers along side all their resources (ie. Estimates, Invoices, Payments and Addresses)
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function delete(Request $request)
{
foreach ($request->id as $id) {

View File

@ -15,6 +15,12 @@ use Illuminate\Support\Facades\DB;
class DashboardController extends Controller
{
/**
* Retrieve Dashboard details
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
$invoiceTotals = [];
@ -30,7 +36,8 @@ class DashboardController extends Controller
$start = Carbon::now();
$end = Carbon::now();
$terms = explode('-', $fiscalYear);
if ($terms[0] < $start->month) {
if ($terms[0] <= $start->month) {
$startDate->month($terms[0])->startOfMonth();
$start->month($terms[0])->startOfMonth();
$end->month($terms[0])->endOfMonth();
@ -87,6 +94,7 @@ class DashboardController extends Controller
}
$start->subMonth()->endOfMonth();
$salesTotal = Invoice::whereCompany($request->header('company'))
->whereBetween(
'invoice_date',
@ -137,6 +145,11 @@ class DashboardController extends Controller
]);
}
/**
* Retrive Expense Chart data
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getExpenseChartData(Request $request)
{
$expensesCategories = Expense::with('category')

View File

@ -56,25 +56,43 @@ class EstimatesController extends Controller
public function create(Request $request)
{
$nextEstimateNumber = 'EST-'.Estimate::getNextEstimateNumber();
$estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company'));
$estimate_num_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company'));
$nextEstimateNumberAttribute = null;
$nextEstimateNumber = Estimate::getNextEstimateNumber($estimate_prefix);
if ($estimate_num_auto_generate == "YES") {
$nextEstimateNumberAttribute = $nextEstimateNumber;
}
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
$customers = User::where('role', 'customer')->get();
return response()->json([
'customers' => $customers,
'nextEstimateNumber' => $nextEstimateNumber,
'nextEstimateNumberAttribute' => $nextEstimateNumberAttribute,
'nextEstimateNumber' => $estimate_prefix.'-'.$nextEstimateNumber,
'taxes' => Tax::whereCompany($request->header('company'))->latest()->get(),
'items' => Item::whereCompany($request->header('company'))->get(),
'tax_per_item' => $tax_per_item,
'discount_per_item' => $discount_per_item,
'estimateTemplates' => EstimateTemplate::all(),
'shareable_link' => ''
'shareable_link' => '',
'estimate_prefix' => $estimate_prefix
]);
}
public function store(EstimatesRequest $request)
{
$estimate_number = explode("-",$request->estimate_number);
$number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1]));
Validator::make($number_attributes, [
'estimate_number' => 'required|unique:estimates,estimate_number'
])->validate();
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
$status = Estimate::STATUS_DRAFT;
@ -101,7 +119,7 @@ class EstimatesController extends Controller
$estimate = Estimate::create([
'estimate_date' => $estimate_date,
'expiry_date' => $expiry_date,
'estimate_number' => $request->estimate_number,
'estimate_number' => $number_attributes['estimate_number'],
'reference_number' => $request->reference_number,
'user_id' => $request->user_id,
'company_id' => $request->header('company'),
@ -127,7 +145,7 @@ class EstimatesController extends Controller
if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) {
foreach ($estimateItem['taxes'] as $tax) {
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$tax['company_id'] = $request->header('company');
$item->taxes()->create($tax);
}
@ -137,7 +155,7 @@ class EstimatesController extends Controller
if ($request->has('taxes')) {
foreach ($request->taxes as $tax) {
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$tax['company_id'] = $request->header('company');
$estimate->taxes()->create($tax);
}
@ -150,10 +168,6 @@ class EstimatesController extends Controller
$data['user'] = User::find($userId)->toArray();
$data['company'] = Company::find($estimate->company_id);
$email = $data['user']['email'];
$notificationEmail = CompanySetting::getSetting(
'notification_email',
$request->header('company')
);
if (!$email) {
return response()->json([
@ -161,13 +175,13 @@ class EstimatesController extends Controller
]);
}
if (!$notificationEmail) {
if (!config('mail.from.name')) {
return response()->json([
'error' => 'notification_email_does_not_exist'
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new EstimatePdf($data, $notificationEmail));
\Mail::to($email)->send(new EstimatePdf($data));
}
$estimate = Estimate::with([
@ -216,26 +230,33 @@ class EstimatesController extends Controller
return response()->json( [
'customers' => $customers,
'nextEstimateNumber' => $estimate->estimate_number,
'nextEstimateNumber' => $estimate->getEstimateNumAttribute(),
'taxes' => Tax::latest()->whereCompany($request->header('company'))->get(),
'estimate' => $estimate,
'items' => Item::whereCompany($request->header('company'))->latest()->get(),
'estimateTemplates' => EstimateTemplate::all(),
'tax_per_item' => $estimate->tax_per_item,
'discount_per_item' => $estimate->discount_per_item,
'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash)
'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash),
'estimate_prefix' => $estimate->getEstimatePrefixAttribute()
]);
}
public function update(EstimatesRequest $request, $id)
{
$estimate_number = explode("-",$request->estimate_number);
$number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1]));
Validator::make($number_attributes, [
'estimate_number' => 'required|unique:estimates,estimate_number'.','.$id
])->validate();
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
$estimate = Estimate::find($id);
$estimate->estimate_date = $estimate_date;
$estimate->expiry_date = $expiry_date;
$estimate->estimate_number = $request->estimate_number;
$estimate->estimate_number = $number_attributes['estimate_number'];
$estimate->reference_number = $request->reference_number;
$estimate->user_id = $request->user_id;
$estimate->estimate_template_id = $request->estimate_template_id;
@ -266,7 +287,7 @@ class EstimatesController extends Controller
if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) {
foreach ($estimateItem['taxes'] as $tax) {
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$tax['company_id'] = $request->header('company');
$item->taxes()->create($tax);
}
@ -276,7 +297,7 @@ class EstimatesController extends Controller
if ($request->has('taxes')) {
foreach ($request->taxes as $tax) {
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$tax['company_id'] = $request->header('company');
$estimate->taxes()->create($tax);
}
@ -315,10 +336,6 @@ class EstimatesController extends Controller
$data['company'] = Company::find($estimate->company_id);
$email = $data['user']['email'];
$notificationEmail = CompanySetting::getSetting(
'notification_email',
$request->header('company')
);
if (!$email) {
return response()->json([
@ -326,13 +343,13 @@ class EstimatesController extends Controller
]);
}
if (!$notificationEmail) {
if (!config('mail.from.name')) {
return response()->json([
'error' => 'notification_email_does_not_exist'
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new EstimatePdf($data, $notificationEmail));
\Mail::to($email)->send(new EstimatePdf($data));
if ($estimate->status == Estimate::STATUS_DRAFT) {
$estimate->status = Estimate::STATUS_SENT;
@ -381,6 +398,10 @@ class EstimatesController extends Controller
{
$estimate = Estimate::with(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes'])->find($id);
$invoice_date = Carbon::parse($estimate->estimate_date);
$invoice_prefix = CompanySetting::getSetting(
'invoice_prefix',
$request->header('company')
);
$due_date = Carbon::parse($estimate->estimate_date)->addDays(7);
$tax_per_item = CompanySetting::getSetting(
'tax_per_item',
@ -400,7 +421,7 @@ class EstimatesController extends Controller
$invoice = Invoice::create([
'invoice_date' => $invoice_date,
'due_date' => $due_date,
'invoice_number' => "INV-".Invoice::getNextInvoiceNumber(),
'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix),
'reference_number' => $estimate->reference_number,
'user_id' => $estimate->user_id,
'company_id' => $request->header('company'),

View File

@ -17,7 +17,7 @@ class ExpensesController extends Controller
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
@ -48,7 +48,7 @@ class ExpensesController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function create(Request $request)
{
@ -63,7 +63,7 @@ class ExpensesController extends Controller
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function store(ExpenseRequest $request)
{
@ -91,7 +91,7 @@ class ExpensesController extends Controller
* Display the specified resource.
*
* @param \Crater\Expense $expense
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function show(Expense $expense)
{
@ -102,7 +102,7 @@ class ExpensesController extends Controller
* Show the form for editing the specified resource.
*
* @param $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function edit(Request $request,$id)
{
@ -122,7 +122,7 @@ class ExpensesController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param \Crater\Expense $expense
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function update(ExpenseRequest $request, Expense $expense)
{
@ -150,7 +150,7 @@ class ExpensesController extends Controller
* Remove the specified resource from storage.
*
* @param \Crater\Expense $expense
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Expense $expense)
{
@ -175,7 +175,7 @@ class ExpensesController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function uploadReceipts(Request $request, $id)
{
@ -200,6 +200,12 @@ class ExpensesController extends Controller
]);
}
/**
* Retrive details of an expense receipt from storage.
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function showReceipt($id)
{
$expense = Expense::find($id);
@ -226,6 +232,14 @@ class ExpensesController extends Controller
]);
}
/**
* Download an expense receipt from storage.
* @param int $id
* @param strig $hash
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse | \Illuminate\Http\JsonResponse
*/
public function downloadReceipt($id, $hash)
{
$company = Company::where('unique_hash', $hash)->first();

View File

@ -6,6 +6,7 @@ use Crater\Invoice;
use PDF;
use Crater\CompanySetting;
use Crater\Estimate;
use Crater\Payment;
use Crater\User;
use Crater\Company;
use Crater\InvoiceTemplate;
@ -118,6 +119,11 @@ class FrontendController extends Controller
return $pdf->stream();
}
/**
*
* @return \Illuminate\Http\Response
*/
public function getCustomerInvoicePdf($id)
{
$invoice = Invoice::with([
@ -371,4 +377,34 @@ class FrontendController extends Controller
return $pdf->stream();
}
public function getPaymentPdf($id)
{
$payment = Payment::with([
'user',
'invoice',
'paymentMethod'
])
->where('unique_hash', $id)
->first();
$company = Company::find($payment->company_id);
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
$logo = $company->getMedia('logo')->first();
if($logo) {
$logo = $logo->getFullUrl();
}
view()->share([
'payment' => $payment,
'company_address' => $companyAddress,
'logo' => $logo ?? null
]);
$pdf = PDF::loadView('app.pdf.payment.payment');
return $pdf->stream();
}
}

View File

@ -27,7 +27,7 @@ class InvoicesController extends Controller
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
@ -60,20 +60,30 @@ class InvoicesController extends Controller
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function create(Request $request)
{
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
$nextInvoiceNumber = "INV-".Invoice::getNextInvoiceNumber();
$invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company'));
$invoice_num_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company'));
$nextInvoiceNumberAttribute = null;
$nextInvoiceNumber = Invoice::getNextInvoiceNumber($invoice_prefix);
if ($invoice_num_auto_generate == "YES") {
$nextInvoiceNumberAttribute = $nextInvoiceNumber;
}
return response()->json([
'nextInvoiceNumber' => $nextInvoiceNumber,
'nextInvoiceNumberAttribute' => $nextInvoiceNumberAttribute,
'nextInvoiceNumber' => $invoice_prefix.'-'.$nextInvoiceNumber,
'items' => Item::with('taxes')->whereCompany($request->header('company'))->get(),
'invoiceTemplates' => InvoiceTemplate::all(),
'tax_per_item' => $tax_per_item,
'discount_per_item' => $discount_per_item
'discount_per_item' => $discount_per_item,
'invoice_prefix' => $invoice_prefix
]);
}
@ -81,10 +91,17 @@ class InvoicesController extends Controller
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function store(Requests\InvoicesRequest $request)
{
$invoice_number = explode("-",$request->invoice_number);
$number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1]));
Validator::make($number_attributes, [
'invoice_number' => 'required|unique:invoices,invoice_number'
])->validate();
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
$status = Invoice::STATUS_DRAFT;
@ -99,7 +116,7 @@ class InvoicesController extends Controller
$invoice = Invoice::create([
'invoice_date' => $invoice_date,
'due_date' => $due_date,
'invoice_number' => $request->invoice_number,
'invoice_number' => $number_attributes['invoice_number'],
'reference_number' => $request->reference_number,
'user_id' => $request->user_id,
'company_id' => $request->header('company'),
@ -128,8 +145,7 @@ class InvoicesController extends Controller
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
foreach ($invoiceItem['taxes'] as $tax) {
$tax['company_id'] = $request->header('company');
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$item->taxes()->create($tax);
}
}
@ -140,7 +156,7 @@ class InvoicesController extends Controller
foreach ($request->taxes as $tax) {
$tax['company_id'] = $request->header('company');
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$invoice->taxes()->create($tax);
}
}
@ -151,11 +167,6 @@ class InvoicesController extends Controller
$data['user'] = User::find($request->user_id)->toArray();
$data['company'] = Company::find($invoice->company_id);
$notificationEmail = CompanySetting::getSetting(
'notification_email',
$request->header('company')
);
$email = $data['user']['email'];
if (!$email) {
@ -164,13 +175,13 @@ class InvoicesController extends Controller
]);
}
if (!$notificationEmail) {
if (!config('mail.from.name')) {
return response()->json([
'error' => 'notification_email_does_not_exist'
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new invoicePdf($data, $notificationEmail));
\Mail::to($email)->send(new invoicePdf($data));
}
$invoice = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])->find($invoice->id);
@ -185,7 +196,7 @@ class InvoicesController extends Controller
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function show(Request $request, $id)
{
@ -209,7 +220,7 @@ class InvoicesController extends Controller
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function edit(Request $request,$id)
{
@ -222,12 +233,13 @@ class InvoicesController extends Controller
])->find($id);
return response()->json([
'nextInvoiceNumber' => $invoice->invoice_number,
'nextInvoiceNumber' => $invoice->getInvoiceNumAttribute(),
'invoice' => $invoice,
'invoiceTemplates' => InvoiceTemplate::all(),
'tax_per_item' => $invoice->tax_per_item,
'discount_per_item' => $invoice->discount_per_item,
'shareable_link' => url('/invoices/pdf/'.$invoice->unique_hash)
'shareable_link' => url('/invoices/pdf/'.$invoice->unique_hash),
'invoice_prefix' => $invoice->getInvoicePrefixAttribute()
]);
}
@ -236,10 +248,17 @@ class InvoicesController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function update(Requests\InvoicesRequest $request, $id)
{
$invoice_number = explode("-",$request->invoice_number);
$number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1]));
Validator::make($number_attributes, [
'invoice_number' => 'required|unique:invoices,invoice_number'.','.$id
])->validate();
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
@ -268,7 +287,7 @@ class InvoicesController extends Controller
$invoice->invoice_date = $invoice_date;
$invoice->due_date = $due_date;
$invoice->invoice_number = $request->invoice_number;
$invoice->invoice_number = $number_attributes['invoice_number'];
$invoice->reference_number = $request->reference_number;
$invoice->user_id = $request->user_id;
$invoice->invoice_template_id = $request->invoice_template_id;
@ -292,7 +311,6 @@ class InvoicesController extends Controller
foreach ($oldTaxes as $oldTax) {
Tax::destroy($oldTax['id']);
}
foreach ($invoiceItems as $invoiceItem) {
$invoiceItem['company_id'] = $request->header('company');
$item = $invoice->items()->create($invoiceItem);
@ -300,8 +318,7 @@ class InvoicesController extends Controller
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
foreach ($invoiceItem['taxes'] as $tax) {
$tax['company_id'] = $request->header('company');
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$item->taxes()->create($tax);
}
}
@ -312,7 +329,7 @@ class InvoicesController extends Controller
foreach ($request->taxes as $tax) {
$tax['company_id'] = $request->header('company');
if ($tax['amount']) {
if (gettype($tax['amount']) !== "NULL") {
$invoice->taxes()->create($tax);
}
}
@ -331,7 +348,7 @@ class InvoicesController extends Controller
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\JsonResponse
*/
public function destroy($id)
{
@ -369,6 +386,14 @@ class InvoicesController extends Controller
]);
}
/**
* Mail a specific invoice to the correponding cusitomer's email address.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function sendInvoice(Request $request)
{
$invoice = Invoice::findOrFail($request->id);
@ -378,10 +403,6 @@ class InvoicesController extends Controller
$data['user'] = User::find($userId)->toArray();
$data['company'] = Company::find($invoice->company_id);
$email = $data['user']['email'];
$notificationEmail = CompanySetting::getSetting(
'notification_email',
$request->header('company')
);
if (!$email) {
return response()->json([
@ -389,13 +410,13 @@ class InvoicesController extends Controller
]);
}
if (!$notificationEmail) {
if (!config('mail.from.name')) {
return response()->json([
'error' => 'notification_email_does_not_exist'
'error' => 'from_email_does_not_exist'
]);
}
\Mail::to($email)->send(new invoicePdf($data, $notificationEmail));
\Mail::to($email)->send(new invoicePdf($data));
if ($invoice->status == Invoice::STATUS_DRAFT) {
$invoice->status = Invoice::STATUS_SENT;
@ -409,6 +430,13 @@ class InvoicesController extends Controller
]);
}
/**
* Mark a specific invoice as sent.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function markAsSent(Request $request)
{
$invoice = Invoice::findOrFail($request->id);
@ -421,6 +449,13 @@ class InvoicesController extends Controller
]);
}
/**
* Mark a specific invoice as paid.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function markAsPaid(Request $request)
{
$invoice = Invoice::findOrFail($request->id);
@ -434,6 +469,14 @@ class InvoicesController extends Controller
]);
}
/**
* Retrive a specified user's unpaid invoices from storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function getCustomersUnpaidInvoices(Request $request, $id)
{
$invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID)
@ -445,4 +488,94 @@ class InvoicesController extends Controller
'invoices' => $invoices
]);
}
public function cloneInvoice(Request $request)
{
$oldInvoice = Invoice::with([
'items.taxes',
'user',
'invoiceTemplate',
'taxes.taxType'
])
->find($request->id);
$date = Carbon::now();
$invoice_prefix = CompanySetting::getSetting(
'invoice_prefix',
$request->header('company')
);
$tax_per_item = CompanySetting::getSetting(
'tax_per_item',
$request->header('company')
) ? CompanySetting::getSetting(
'tax_per_item',
$request->header('company')
) : 'NO';
$discount_per_item = CompanySetting::getSetting(
'discount_per_item',
$request->header('company')
) ? CompanySetting::getSetting(
'discount_per_item',
$request->header('company')
) : 'NO';
$invoice = Invoice::create([
'invoice_date' => $date,
'due_date' => $date,
'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix),
'reference_number' => $oldInvoice->reference_number,
'user_id' => $oldInvoice->user_id,
'company_id' => $request->header('company'),
'invoice_template_id' => 1,
'status' => Invoice::STATUS_DRAFT,
'paid_status' => Invoice::STATUS_UNPAID,
'sub_total' => $oldInvoice->sub_total,
'discount' => $oldInvoice->discount,
'discount_type' => $oldInvoice->discount_type,
'discount_val' => $oldInvoice->discount_val,
'total' => $oldInvoice->total,
'due_amount' => $oldInvoice->total,
'tax_per_item' => $oldInvoice->tax_per_item,
'discount_per_item' => $oldInvoice->discount_per_item,
'tax' => $oldInvoice->tax,
'notes' => $oldInvoice->notes,
'unique_hash' => str_random(60)
]);
$invoiceItems = $oldInvoice->items->toArray();
foreach ($invoiceItems as $invoiceItem) {
$invoiceItem['company_id'] = $request->header('company');
$invoiceItem['name'] = $invoiceItem['name'];
$item = $invoice->items()->create($invoiceItem);
if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) {
foreach ($invoiceItem['taxes'] as $tax) {
$tax['company_id'] = $request->header('company');
if ($tax['amount']) {
$item->taxes()->create($tax);
}
}
}
}
if ($oldInvoice->taxes) {
foreach ($oldInvoice->taxes->toArray() as $tax) {
$tax['company_id'] = $request->header('company');
$invoice->taxes()->create($tax);
}
}
$invoice = Invoice::with([
'items',
'user',
'invoiceTemplate',
'taxes'
])->find($invoice->id);
return response()->json([
'invoice' => $invoice
]);
}
}

View File

@ -14,14 +14,17 @@ class ItemsController extends Controller
{
$limit = $request->has('limit') ? $request->limit : 10;
$items = Item::applyFilters($request->only([
$items = Item::with(['taxes'])
->leftJoin('units', 'units.id', '=', 'items.unit_id')
->applyFilters($request->only([
'search',
'price',
'unit',
'unit_id',
'orderByField',
'orderBy'
]))
->whereCompany($request->header('company'))
->select('items.*', 'units.name as unit_name')
->latest()
->paginate($limit);
@ -33,7 +36,7 @@ class ItemsController extends Controller
public function edit(Request $request, $id)
{
$item = Item::with('taxes')->find($id);
$item = Item::with(['taxes', 'unit'])->find($id);
return response()->json([
'item' => $item,
@ -43,11 +46,18 @@ class ItemsController extends Controller
]);
}
/**
* Create Item.
*
* @param Crater\Http\Requests\ItemsRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(Requests\ItemsRequest $request)
{
$item = new Item();
$item->name = $request->name;
$item->unit = $request->unit;
$item->unit_id = $request->unit_id;
$item->description = $request->description;
$item->company_id = $request->header('company');
$item->price = $request->price;
@ -67,11 +77,18 @@ class ItemsController extends Controller
]);
}
/**
* Update an existing Item.
*
* @param Crater\Http\Requests\ItemsRequest $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(Requests\ItemsRequest $request, $id)
{
$item = Item::find($id);
$item->name = $request->name;
$item->unit = $request->unit;
$item->unit_id = $request->unit_id;
$item->description = $request->description;
$item->price = $request->price;
$item->save();
@ -96,6 +113,13 @@ class ItemsController extends Controller
]);
}
/**
* Delete an existing Item.
*
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function destroy($id)
{
$data = Item::deleteItem($id);
@ -111,12 +135,20 @@ class ItemsController extends Controller
]);
}
/**
* Delete a list of existing Items.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function delete(Request $request)
{
$items = [];
foreach ($request->id as $id) {
$item = Item::deleteItem($id);
if (!$item) {
if ($item) {
array_push($items, $id);
}
}

View File

@ -6,6 +6,12 @@ use Crater\Country;
class LocationController extends Controller
{
/**
* Retrive a list of Countries.
*
* @return \Illuminate\Http\JsonResponse
*/
public function getCountries()
{
return response()->json([

View File

@ -18,6 +18,13 @@ use Illuminate\Support\Facades\Artisan;
class OnboardingController extends Controller
{
/**
* Retrieve Onboarding data.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getOnboardingData(Request $request)
{
if (!\Storage::disk('local')->has('database_created')) {
@ -37,9 +44,13 @@ class OnboardingController extends Controller
$date_formats = DateFormatter::get_list();
$time_zones = TimeZones::get_list();
$languages = [
["code"=>"ar", "name" => "Arabic"],
["code"=>"en", "name" => "English"],
["code"=>"fr", "name" => "French"],
["code"=>"es", "name" => "Spanish"]
["code"=>"es", "name" => "Spanish"],
["code"=>"ar", "name" => "العربية"],
["code"=>"de", "name" => "German"],
["code"=>"pt-br", "name" => "Portuguese (Brazilian)"]
];
$fiscal_years = [
['key' => 'january-december' , 'value' => '1-12'],
@ -72,6 +83,13 @@ class OnboardingController extends Controller
]);
}
/**
* Setup Admin Profile.
*
* @param \Crater\Http\Requests\ProfileRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function adminProfile(ProfileRequest $request)
{
$setting = Setting::getSetting('profile_complete');
@ -97,6 +115,12 @@ class OnboardingController extends Controller
]);
}
/**
* Setup Admin Avatar.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function uploadAdminAvatar(Request $request)
{
$setting = Setting::getSetting('profile_complete');
@ -123,6 +147,12 @@ class OnboardingController extends Controller
]);
}
/**
* Setup Admin Company.
*
* @param \Crater\Http\Requests\CompanyRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function adminCompany(CompanyRequest $request)
{
$setting = Setting::getSetting('profile_complete');
@ -174,6 +204,13 @@ class OnboardingController extends Controller
]);
}
/**
* Setup Company Settings.
*
* @param \Crater\Http\Requests\CompanySettingRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function companySettings(CompanySettingRequest $request)
{
$setting = Setting::getSetting('profile_complete');
@ -202,6 +239,45 @@ class OnboardingController extends Controller
);
}
$invoices = [
'invoice_auto_generate' => 'YES',
'invoice_prefix' => 'INV'
];
foreach ($invoices as $key => $value) {
CompanySetting::setSetting(
$key,
$value,
$user->company_id
);
}
$estimates = [
'estimate_prefix' => 'EST',
'estimate_auto_generate' => 'YES'
];
foreach ($estimates as $key => $value) {
CompanySetting::setSetting(
$key,
$value,
$user->company_id
);
}
$payments = [
'payment_prefix' => 'PAY',
'payment_auto_generate' => 'YES'
];
foreach ($payments as $key => $value) {
CompanySetting::setSetting(
$key,
$value,
$user->company_id
);
}
$colors = [
'primary_text_color' => '#5851D8',
'heading_text_color' => '#595959',
@ -232,13 +308,24 @@ class OnboardingController extends Controller
Artisan::call('passport:install --force');
Artisan::call('db:seed', ['--class' => 'PaymentMethodSeeder', '--force' => true]);
Artisan::call('db:seed', ['--class' => 'UnitSeeder', '--force' => true]);
$client = DB::table('oauth_clients')->find(2);
$path = base_path('.env');
if (file_exists($path)) {
file_put_contents($path, str_replace(
'PROXY_OAUTH_CLIENT_SECRET='.config('auth.proxy.client_secret'), 'PROXY_OAUTH_CLIENT_SECRET='.$client->secret, file_get_contents($path)
'PROXY_OAUTH_CLIENT_SECRET='.config('auth.proxy.client_secret'),
'PROXY_OAUTH_CLIENT_SECRET='.$client->secret,
file_get_contents($path)
));
file_put_contents($path, str_replace(
'APP_DEBUG=true',
'APP_DEBUG=false',
file_get_contents($path)
));
}

View File

@ -4,12 +4,16 @@ namespace Crater\Http\Controllers;
use Illuminate\Http\Request;
use Crater\CompanySetting;
use Crater\Currency;
use Crater\Company;
use Crater\Invoice;
use Crater\Payment;
use Crater\PaymentMethod;
use Carbon\Carbon;
use function MongoDB\BSON\toJSON;
use Crater\User;
use Crater\Http\Requests\PaymentRequest;
use Validator;
use Crater\Mail\PaymentPdf;
class PaymentController extends Controller
{
@ -22,19 +26,20 @@ class PaymentController extends Controller
{
$limit = $request->has('limit') ? $request->limit : 10;
$payments = Payment::with('user', 'invoice')
$payments = Payment::with(['user', 'invoice', 'paymentMethod'])
->join('users', 'users.id', '=', 'payments.user_id')
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
->leftJoin('payment_methods', 'payment_methods.id', '=', 'payments.payment_method_id')
->applyFilters($request->only([
'search',
'payment_number',
'payment_mode',
'payment_method_id',
'customer_id',
'orderByField',
'orderBy'
]))
->whereCompany($request->header('company'))
->select('payments.*', 'users.name', 'invoices.invoice_number')
->select('payments.*', 'users.name', 'invoices.invoice_number', 'payment_methods.name as payment_mode')
->latest()
->paginate($limit);
@ -50,13 +55,27 @@ class PaymentController extends Controller
*/
public function create(Request $request)
{
$nextPaymentNumber = 'PAY-'.Payment::getNextPaymentNumber();
$payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company'));
$payment_num_auto_generate = CompanySetting::getSetting('payment_auto_generate', $request->header('company'));
$nextPaymentNumberAttribute = null;
$nextPaymentNumber = Payment::getNextPaymentNumber($payment_prefix);
if ($payment_num_auto_generate == "YES") {
$nextPaymentNumberAttribute = $nextPaymentNumber;
}
return response()->json([
'customers' => User::where('role', 'customer')
->whereCompany($request->header('company'))
->get(),
'nextPaymentNumber' => $nextPaymentNumber
'paymentMethods' => PaymentMethod::whereCompany($request->header('company'))
->latest()
->get(),
'nextPaymentNumberAttribute' => $nextPaymentNumberAttribute,
'nextPaymentNumber' => $payment_prefix.'-'.$nextPaymentNumber,
'payment_prefix' => $payment_prefix
]);
}
@ -68,6 +87,13 @@ class PaymentController extends Controller
*/
public function store(PaymentRequest $request)
{
$payment_number = explode("-",$request->payment_number);
$number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1]));
Validator::make($number_attributes, [
'payment_number' => 'required|unique:payments,payment_number'
])->validate();
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
if ($request->has('invoice_id') && $request->invoice_id != null) {
@ -90,17 +116,19 @@ class PaymentController extends Controller
$payment = Payment::create([
'payment_date' => $payment_date,
'payment_number' => $request->payment_number,
'payment_number' => $number_attributes['payment_number'],
'user_id' => $request->user_id,
'company_id' => $request->header('company'),
'invoice_id' => $request->invoice_id,
'payment_mode' => $request->payment_mode,
'payment_method_id' => $request->payment_method_id,
'amount' => $request->amount,
'notes' => $request->notes,
'unique_hash' => str_random(60)
]);
return response()->json([
'payment' => $payment,
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
'success' => true
]);
}
@ -113,7 +141,12 @@ class PaymentController extends Controller
*/
public function show($id)
{
//
$payment = Payment::with(['user', 'invoice', 'paymentMethod'])->find($id);
return response()->json([
'payment' => $payment,
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash)
]);
}
/**
@ -124,7 +157,7 @@ class PaymentController extends Controller
*/
public function edit(Request $request, $id)
{
$payment = Payment::with('user', 'invoice')->find($id);
$payment = Payment::with(['user', 'invoice', 'paymentMethod'])->find($id);
$invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID)
->where('user_id', $payment->user_id)->where('due_amount', '>', 0)
@ -135,7 +168,12 @@ class PaymentController extends Controller
'customers' => User::where('role', 'customer')
->whereCompany($request->header('company'))
->get(),
'nextPaymentNumber' => $payment->payment_number,
'paymentMethods' => PaymentMethod::whereCompany($request->header('company'))
->latest()
->get(),
'nextPaymentNumber' => $payment->getPaymentNumAttribute(),
'payment_prefix' => $payment->getPaymentPrefixAttribute(),
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
'payment' => $payment,
'invoices' => $invoices
]);
@ -150,6 +188,13 @@ class PaymentController extends Controller
*/
public function update(PaymentRequest $request, $id)
{
$payment_number = explode("-",$request->payment_number);
$number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1]));
Validator::make($number_attributes, [
'payment_number' => 'required|unique:payments,payment_number'.','.$id
])->validate();
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
$payment = Payment::find($id);
@ -178,16 +223,17 @@ class PaymentController extends Controller
}
$payment->payment_date = $payment_date;
$payment->payment_number = $request->payment_number;
$payment->payment_number = $number_attributes['payment_number'];
$payment->user_id = $request->user_id;
$payment->invoice_id = $request->invoice_id;
$payment->payment_mode = $request->payment_mode;
$payment->payment_method_id = $request->payment_method_id;
$payment->amount = $request->amount;
$payment->notes = $request->notes;
$payment->save();
return response()->json([
'payment' => $payment,
'shareable_link' => url('/payments/pdf/'.$payment->unique_hash),
'success' => true
]);
}
@ -249,4 +295,37 @@ class PaymentController extends Controller
'success' => true
]);
}
public function sendPayment(Request $request)
{
$payment = Payment::findOrFail($request->id);
$data['payment'] = $payment->toArray();
$userId = $data['payment']['user_id'];
$data['user'] = User::find($userId)->toArray();
$data['company'] = Company::find($payment->company_id);
$email = $data['user']['email'];
$notificationEmail = CompanySetting::getSetting(
'notification_email',
$request->header('company')
);
if (!$email) {
return response()->json([
'error' => 'user_email_does_not_exist'
]);
}
if (!$notificationEmail) {
return response()->json([
'error' => 'notification_email_does_not_exist'
]);
}
\Mail::to($email)->send(new PaymentPdf($data, $notificationEmail));
return response()->json([
'success' => true
]);
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace Crater\Http\Controllers;
use Crater\PaymentMethod;
use Illuminate\Http\Request;
use Crater\Http\Requests\PaymentMethodRequest;
class PaymentMethodController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$paymentMethods = PaymentMethod::whereCompany($request->header('company'))
->latest()
->get();
return response()->json([
'paymentMethods' => $paymentMethods
]);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(PaymentMethodRequest $request)
{
$paymentMethod = new PaymentMethod;
$paymentMethod->name = $request->name;
$paymentMethod->company_id = $request->header('company');
$paymentMethod->save();
return response()->json([
'paymentMethod' => $paymentMethod
]);
}
/**
* Display the specified resource.
*
* @param \Crater\PaymentMethod $paymentMethod
* @return \Illuminate\Http\Response
*/
public function show(PaymentMethod $paymentMethod)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \Crater\PaymentMethod $paymentMethod
* @return \Illuminate\Http\Response
*/
public function edit(PaymentMethod $paymentMethod)
{
return response()->json([
'paymentMethod' => $paymentMethod
]);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \Crater\PaymentMethod $paymentMethod
* @return \Illuminate\Http\Response
*/
public function update(PaymentMethodRequest $request, PaymentMethod $paymentMethod)
{
$paymentMethod->name = $request->name;
$paymentMethod->company_id = $request->header('company');
$paymentMethod->save();
return response()->json([
'paymentMethod' => $paymentMethod
]);
}
/**
* Remove the specified resource from storage.
*
* @param \Crater\PaymentMethod $paymentMethod
* @return \Illuminate\Http\Response
*/
public function destroy(PaymentMethod $paymentMethod)
{
$payments = $paymentMethod->payments;
if ($payments->count() > 0) {
return response()->json([
'error' => 'payments_attached'
]);
}
$paymentMethod->delete();
return response()->json([
'success' => 'Payment method deleted successfully'
]);
}
}

View File

@ -4,9 +4,18 @@ namespace Crater\Http\Controllers;
use Illuminate\Http\Request;
use Crater\Setting;
use Crater\Mail\TestMail;
use Mail;
class SettingsController extends Controller
{
/**
* Retrive App Version.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getAppVersion(Request $request)
{
$version = Setting::getSetting('version');
@ -16,4 +25,18 @@ class SettingsController extends Controller
]);
}
public function testEmailConfig(Request $request)
{
$this->validate($request, [
'to' => 'required|email',
'subject' => 'required',
'message' => 'required'
]);
Mail::to($request->to)->send(new TestMail($request->subject, $request->message));
return response()->json([
'success' => true
]);
}
}

View File

@ -0,0 +1,119 @@
<?php
namespace Crater\Http\Controllers;
use Crater\Unit;
use Illuminate\Http\Request;
use Crater\Http\Requests\UnitRequest;
class UnitController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$units = Unit::whereCompany($request->header('company'))
->latest()
->get();
return response()->json([
'units' => $units
]);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(UnitRequest $request)
{
$unit = new Unit;
$unit->name = $request->name;
$unit->company_id = $request->header('company');
$unit->save();
return response()->json([
'unit' => $unit
]);
}
/**
* Display the specified resource.
*
* @param \Crater\Unit $unit
* @return \Illuminate\Http\Response
*/
public function show(Unit $unit)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \Crater\Unit $unit
* @return \Illuminate\Http\Response
*/
public function edit(Unit $unit)
{
return response()->json([
'unit' => $unit
]);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \Crater\Unit $unit
* @return \Illuminate\Http\Response
*/
public function update(UnitRequest $request, Unit $unit)
{
$unit->name = $request->name;
$unit->company_id = $request->header('company');
$unit->save();
return response()->json([
'unit' => $unit
]);
}
/**
* Remove the specified resource from storage.
*
* @param \Crater\Unit $unit
* @return \Illuminate\Http\Response
*/
public function destroy(Unit $unit)
{
$items = $unit->items;
if ($items->count() > 0) {
return response()->json([
'error' => 'items_attached'
]);
}
$unit->delete();
return response()->json([
'success' => 'Unit deleted successfully'
]);
}
}

View File

@ -7,6 +7,8 @@ use Crater\User;
use Crater\Currency;
use Crater\Setting;
use Crater\Item;
use Crater\PaymentMethod;
use Crater\Unit;
use Crater\TaxType;
use DB;
use Carbon\Carbon;
@ -46,10 +48,18 @@ class UsersController extends Controller
$request->header('company')
);
$items = Item::all();
$items = Item::with('taxes')->get();
$taxTypes = TaxType::latest()->get();
$paymentMethods = PaymentMethod::whereCompany($request->header('company'))
->latest()
->get();
$units = Unit::whereCompany($request->header('company'))
->latest()
->get();
return response()->json([
'user' => $user,
'customers' => $customers,
@ -61,6 +71,8 @@ class UsersController extends Controller
'items' => $items,
'taxTypes' => $taxTypes,
'moment_date_format' => $moment_date_format,
'paymentMethods' => $paymentMethods,
'units' => $units,
'fiscal_year' => $fiscal_year,
]);
}

View File

@ -25,7 +25,6 @@ class EstimatesRequest extends FormRequest
$rules = [
'estimate_date' => 'required',
'expiry_date' => 'required',
'estimate_number' => 'required|unique:estimates,estimate_number',
'user_id' => 'required',
'discount' => 'required',
'discount_val' => 'required',
@ -41,10 +40,6 @@ class EstimatesRequest extends FormRequest
'items.*.price' => 'required'
];
if ($this->getMethod() == 'PUT') {
$rules['estimate_number'] = $rules['estimate_number'].','.$this->get('id');
}
return $rules;
}
}

View File

@ -25,7 +25,6 @@ class InvoicesRequest extends FormRequest
$rules = [
'invoice_date' => 'required',
'due_date' => 'required',
'invoice_number' => 'required|unique:invoices,invoice_number',
'user_id' => 'required',
'discount' => 'required',
'discount_val' => 'required',
@ -41,10 +40,6 @@ class InvoicesRequest extends FormRequest
'items.*.price' => 'required'
];
if ($this->getMethod() == 'PUT') {
$rules['invoice_number'] = $rules['invoice_number'].','.$this->get('id');
}
return $rules;
}
}

View File

@ -40,12 +40,9 @@ class MailEnvironmentRequest extends FormRequest
case 'mailgun':
return [
'mail_driver' => 'required|string',
'mail_host' => 'required|string',
'mail_port' => 'required',
'mail_mailgun_domain' => 'required|string',
'mail_mailgun_secret' => 'required|string',
'mail_mailgun_endpoint' => 'required|string',
'mail_encryption' => 'required|string',
'from_name' => 'required|string',
'from_mail' => 'required|string',
];

View File

@ -0,0 +1,40 @@
<?php
namespace Crater\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class PaymentMethodRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$data = [
'name' => 'required|unique:payment_methods,name'
];
if ($this->getMethod() == 'PUT') {
$data['name'] = [
'required',
Rule::unique('payment_methods')->ignore($this->route('payment_method'), 'id')
];
}
return $data;
}
}

View File

@ -24,15 +24,10 @@ class PaymentRequest extends FormRequest
{
$rules = [
'payment_date' => 'required',
'payment_number' => 'required|unique:payments,payment_number',
'user_id' => 'required',
'amount' => 'required',
];
if ($this->getMethod() == 'PUT') {
$rules['payment_number'] = $rules['payment_number'].','.$this->route('payment');
}
return $rules;
}
}

View File

@ -30,7 +30,7 @@ class ProfileRequest extends FormRequest
case 'POST':
return [
'name' => 'required',
'password' => 'required',
'password' => 'required|min:8',
'address_street_1' => 'max:255',
'address_street_2' => 'max:255',
'email' => [

View File

@ -0,0 +1,40 @@
<?php
namespace Crater\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UnitRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$data = [
'name' => 'required|unique:units,name'
];
if ($this->getMethod() == 'PUT') {
$data['name'] = [
'required',
Rule::unique('units')->ignore($this->route('unit'), 'id')
];
}
return $data;
}
}

View File

@ -66,10 +66,14 @@ class Invoice extends Model
'formattedDueDate'
];
public static function getNextInvoiceNumber()
public static function getNextInvoiceNumber($value)
{
// Get the last created order
$lastOrder = Invoice::orderBy('created_at', 'desc')->first();
$lastOrder = Invoice::where('invoice_number', 'LIKE', $value . '-%')
->orderBy('created_at', 'desc')
->first();
if (!$lastOrder) {
// We get here if there is no order at all
// If there is no number set it to 0, which will be 1 at the end.
@ -143,10 +147,15 @@ class Invoice extends Model
public function getInvoiceNumAttribute()
{
$position = $this->strposX($this->invoice_number, "-", 2) + 1;
$position = $this->strposX($this->invoice_number, "-", 1) + 1;
return substr($this->invoice_number, $position);
}
public function getInvoicePrefixAttribute () {
$prefix = explode("-", $this->invoice_number)[0];
return $prefix;
}
public function getFormattedCreatedAtAttribute($value)
{
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);

View File

@ -24,19 +24,24 @@ class Item extends Model
'formattedCreatedAt'
];
public function unit()
{
return $this->belongsTo(Unit::class);
}
public function scopeWhereSearch($query, $search)
{
return $query->where('name', 'LIKE', '%'.$search.'%');
return $query->where('items.name', 'LIKE', '%'.$search.'%');
}
public function scopeWherePrice($query, $price)
{
return $query->where('price', $price);
return $query->where('items.price', $price);
}
public function scopeWhereUnit($query, $unit)
public function scopeWhereUnit($query, $unit_id)
{
return $query->where('unit', $unit);
return $query->where('items.unit_id', $unit_id);
}
public function scopeWhereOrder($query, $orderByField, $orderBy)
@ -56,8 +61,8 @@ class Item extends Model
$query->wherePrice($filters->get('price'));
}
if ($filters->get('unit')) {
$query->whereUnit($filters->get('unit'));
if ($filters->get('unit_id')) {
$query->whereUnit($filters->get('unit_id'));
}
if ($filters->get('orderByField') || $filters->get('orderBy')) {
@ -80,7 +85,7 @@ class Item extends Model
public function scopeWhereCompany($query, $company_id)
{
$query->where('company_id', $company_id);
$query->where('items.company_id', $company_id);
}
public function invoiceItems()

View File

@ -6,7 +6,6 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Database\Schema\Blueprint;
use Crater\Listeners\Updates\Listener;
use Crater\Listeners\Updates\v2\Version200;
use Crater\Events\UpdateFinished;
use Crater\Setting;
use Crater\Address;

View File

@ -0,0 +1,40 @@
<?php
namespace Crater\Listeners\Updates\v2;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Crater\Events\UpdateFinished;
use Crater\Listeners\Updates\Listener;
use Crater\Setting;
class Version202 extends Listener
{
const VERSION = '2.0.2';
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle(UpdateFinished $event)
{
if ($this->isListenerFired($event)) {
return;
}
// Update Crater app version
Setting::setSetting('version', static::VERSION);
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace Crater\Listeners\Updates\v2;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Crater\Events\UpdateFinished;
use Crater\Listeners\Updates\Listener;
use Crater\Setting;
use Crater\CompanySetting;
class Version210 extends Listener
{
const VERSION = '2.1.0';
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle(UpdateFinished $event)
{
if ($this->isListenerFired($event)) {
return;
}
// Add initial auto generate value
$this->addAutoGenerateSettings();
// Update Crater app version
Setting::setSetting('version', static::VERSION);
}
private function addAutoGenerateSettings()
{
$settings = [
'invoice_auto_generate' => 'YES',
'invoice_prefix' => 'INV',
'estimate_prefix' => 'EST',
'estimate_auto_generate' => 'YES',
'payment_prefix' => 'PAY',
'payment_auto_generate' => 'YES'
];
foreach ($settings as $key => $value) {
CompanySetting::setSetting(
$key,
$value,
auth()->user()->company->id
);
}
}
}

View File

@ -0,0 +1,162 @@
<?php
namespace Crater\Listeners\Updates\v3;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Crater\Setting;
use Crater\Unit;
use Crater\PaymentMethod;
use Crater\Currency;
use Crater\Payment;
use Crater\Item;
use Crater\User;
use Crater\Listeners\Updates\Listener;
use Illuminate\Database\Schema\Blueprint;
class Version300 extends Listener
{
const VERSION = '3.0.0';
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
if ($this->isListenerFired($event)) {
return;
}
$this->changeMigrations();
$this->addSeederData();
$this->databaseChanges();
$this->changeMigrations(true);
Setting::setSetting('version', static::VERSION);
}
public function changeMigrations($removeColumn = false)
{
if ($removeColumn) {
\Schema::table('items', function (Blueprint $table) {
$table->dropColumn('unit');
});
\Schema::table('payments', function (Blueprint $table) {
$table->dropColumn('payment_mode');
});
return true;
}
\Schema::create('units', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies');
$table->timestamps();
});
\Schema::table('items', function (Blueprint $table) {
$table->integer('unit_id')->unsigned()->nullable();
$table->foreign('unit_id')->references('id')->on('units')->onDelete('cascade');
});
\Schema::create('payment_methods', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies');
$table->timestamps();
});
\Schema::table('payments', function (Blueprint $table) {
$table->string('unique_hash')->nullable();
$table->integer('payment_method_id')->unsigned()->nullable();
$table->foreign('payment_method_id')->references('id')->on('payment_methods')->onDelete('cascade');
});
return true;
}
public function addSeederData()
{
$company_id = User::where('role', 'admin')->first()->company_id;
Unit::create(['name' => 'box', 'company_id' => $company_id]);
Unit::create(['name' => 'cm', 'company_id' => $company_id]);
Unit::create(['name' => 'dz', 'company_id' => $company_id]);
Unit::create(['name' => 'ft', 'company_id' => $company_id]);
Unit::create(['name' => 'g', 'company_id' => $company_id]);
Unit::create(['name' => 'in', 'company_id' => $company_id]);
Unit::create(['name' => 'kg', 'company_id' => $company_id]);
Unit::create(['name' => 'km', 'company_id' => $company_id]);
Unit::create(['name' => 'lb', 'company_id' => $company_id]);
Unit::create(['name' => 'mg', 'company_id' => $company_id]);
Unit::create(['name' => 'pc', 'company_id' => $company_id]);
PaymentMethod::create(['name' => 'Cash', 'company_id' => $company_id]);
PaymentMethod::create(['name' => 'Check', 'company_id' => $company_id]);
PaymentMethod::create(['name' => 'Credit Card', 'company_id' => $company_id]);
PaymentMethod::create(['name' => 'Bank Transfer', 'company_id' => $company_id]);
Currency::create([
'name' => 'Serbian Dinar',
'code' => 'RSD',
'symbol' => 'RSD',
'precision' => '2',
'thousand_separator' => '.',
'decimal_separator' => ','
]);
}
public function databaseChanges()
{
$payments = Payment::all();
if ($payments) {
foreach ($payments as $payment) {
$payment->unique_hash = str_random(60);
$payment->save();
$paymentMethod = PaymentMethod::where('name', $payment->payment_mode)
->first();
if ($paymentMethod) {
$payment->payment_method_id = $paymentMethod->id;
$payment->save();
}
}
}
$items = Item::all();
if ($items) {
foreach ($items as $item) {
$unit = Unit::where('name', $item->unit)
->first();
if ($unit) {
$item->unit_id = $unit->id;
$item->save();
}
}
}
}
}

View File

@ -12,17 +12,14 @@ class EstimatePdf extends Mailable
public $data = [];
public $notificationEmail = '';
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($data, $notificationEmail)
public function __construct($data)
{
$this->data = $data;
$this->notificationEmail = $notificationEmail;
}
/**
@ -32,6 +29,6 @@ class EstimatePdf extends Mailable
*/
public function build()
{
return $this->from($this->notificationEmail)->markdown('emails.send.estimate', ['data', $this->data]);
return $this->markdown('emails.send.estimate', ['data', $this->data]);
}
}

38
app/Mail/PaymentPdf.php Normal file
View File

@ -0,0 +1,38 @@
<?php
namespace Crater\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class PaymentPdf extends Mailable
{
use Queueable, SerializesModels;
public $data = [];
public $notificationEmail = '';
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($data, $notificationEmail)
{
$this->data = $data;
$this->notificationEmail = $notificationEmail;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from($this->notificationEmail)->markdown('emails.send.payment', ['data', $this->data]);
}
}

38
app/Mail/TestMail.php Normal file
View File

@ -0,0 +1,38 @@
<?php
namespace Crater\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class TestMail extends Mailable
{
use Queueable, SerializesModels;
public $subject;
public $message;
/**
* Create a new message instance.
*
* @param $subject
* @param $message
*/
public function __construct($subject, $message)
{
$this->subject = $subject;
$this->message = $message;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject($this->subject)->markdown('emails.test')->with([
'my_message' => $this->message
]);
}
}

View File

@ -12,17 +12,14 @@ class invoicePdf extends Mailable
public $data = [];
public $notificationEmail = '';
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($data, $notificationEmail)
public function __construct($data)
{
$this->data = $data;
$this->notificationEmail = $notificationEmail;
}
/**
@ -32,6 +29,6 @@ class invoicePdf extends Mailable
*/
public function build()
{
return $this->from($this->notificationEmail)->markdown('emails.send.invoice', ['data', $this->data]);
return $this->markdown('emails.send.invoice', ['data', $this->data]);
}
}

View File

@ -5,6 +5,7 @@ use Crater\User;
use Crater\Invoice;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Crater\PaymentMethod;
class Payment extends Model
{
@ -19,9 +20,11 @@ class Payment extends Model
protected $fillable = [
'user_id',
'invoice_id',
'payment_method_id',
'payment_date',
'company_id',
'notes',
'unique_hash',
'payment_number',
'payment_mode',
'amount'
@ -32,10 +35,34 @@ class Payment extends Model
'formattedPaymentDate'
];
public static function getNextPaymentNumber()
private function strposX($haystack, $needle, $number)
{
if ($number == '1') {
return strpos($haystack, $needle);
} elseif ($number > '1') {
return strpos(
$haystack,
$needle,
$this->strposX($haystack, $needle, $number - 1) + strlen($needle)
);
} else {
return error_log('Error: Value for parameter $number is out of range');
}
}
public function getPaymentNumAttribute()
{
$position = $this->strposX($this->payment_number, "-", 1) + 1;
return substr($this->payment_number, $position);
}
public static function getNextPaymentNumber($value)
{
// Get the last created order
$payment = Payment::orderBy('created_at', 'desc')->first();
$payment = Payment::where('payment_number', 'LIKE', $value . '-%')
->orderBy('created_at', 'desc')
->first();
if (!$payment) {
// We get here if there is no order at all
// If there is no number set it to 0, which will be 1 at the end.
@ -54,6 +81,12 @@ class Payment extends Model
return sprintf('%06d', intval($number) + 1);
}
public function getPaymentPrefixAttribute ()
{
$prefix= explode("-",$this->payment_number)[0];
return $prefix;
}
public function invoice()
{
return $this->belongsTo(Invoice::class);
@ -64,6 +97,11 @@ class Payment extends Model
return $this->belongsTo(User::class);
}
public function paymentMethod()
{
return $this->belongsTo(PaymentMethod::class);
}
public function getFormattedCreatedAtAttribute($value)
{
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
@ -92,9 +130,9 @@ class Payment extends Model
return $query->where('payments.payment_number', 'LIKE', '%'.$paymentNumber.'%');
}
public function scopePaymentMode($query, $paymentMode)
public function scopePaymentMethod($query, $paymentMethodId)
{
return $query->where('payments.payment_mode', $paymentMode);
return $query->where('payments.payment_method_id', $paymentMethodId);
}
public function scopeApplyFilters($query, array $filters)
@ -109,8 +147,8 @@ class Payment extends Model
$query->paymentNumber($filters->get('payment_number'));
}
if ($filters->get('payment_mode')) {
$query->paymentMode($filters->get('payment_mode'));
if ($filters->get('payment_method_id')) {
$query->paymentMethod($filters->get('payment_method_id'));
}
if ($filters->get('customer_id')) {

25
app/PaymentMethod.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace Crater;
use Illuminate\Database\Eloquent\Model;
class PaymentMethod extends Model
{
protected $fillable = ['name', 'company_id'];
public function payments()
{
return $this->hasMany(Payment::class);
}
public function company()
{
return $this->belongsTo(Company::class);
}
public function scopeWhereCompany($query, $company_id)
{
$query->where('company_id', $company_id);
}
}

View File

@ -8,6 +8,9 @@ use Crater\Events\UpdateFinished;
use Crater\Listeners\Updates\v1\Version110;
use Crater\Listeners\Updates\v2\Version200;
use Crater\Listeners\Updates\v2\Version201;
use Crater\Listeners\Updates\v2\Version202;
use Crater\Listeners\Updates\v2\Version210;
use Crater\Listeners\Updates\v3\Version300;
class EventServiceProvider extends ServiceProvider
{
@ -21,6 +24,9 @@ class EventServiceProvider extends ServiceProvider
Version110::class,
Version200::class,
Version201::class,
Version202::class,
Version210::class,
Version300::class,
],
Registered::class => [
SendEmailVerificationNotification::class,

View File

@ -38,7 +38,7 @@ class EnvironmentManager
'DB_PORT='.config('database.connections.'.config('database.default').'.port')."\n".
'DB_DATABASE='.config('database.connections.'.config('database.default').'.database')."\n".
'DB_USERNAME='.config('database.connections.'.config('database.default').'.username')."\n".
'DB_PASSWORD='.config('database.connections.'.config('database.default').'.password')."\n\n";
'DB_PASSWORD="'.config('database.connections.'.config('database.default').'.password')."\"\n\n";
$newDatabaseData =
'DB_CONNECTION='.$request->database_connection."\n".
@ -46,7 +46,7 @@ class EnvironmentManager
'DB_PORT='.$request->database_port."\n".
'DB_DATABASE='.$request->database_name."\n".
'DB_USERNAME='.$request->database_username."\n".
'DB_PASSWORD='.$request->database_password."\n\n";
'DB_PASSWORD="'.$request->database_password."\"\n\n";
try {
@ -61,7 +61,7 @@ class EnvironmentManager
} catch (Exception $e) {
return [
'error' => $e->getMessage()
'error_message' => $e->getMessage()
];
}

View File

@ -19,7 +19,13 @@ class Updater
$data = null;
$path = null;
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update';
if(env('APP_ENV') === 'development')
{
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update&is_dev=1';
} else {
$url = 'https://craterapp.com/downloads/file/'.$version.'?type=update';
}
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);
@ -115,7 +121,12 @@ class Updater
public static function checkForUpdate()
{
$data = null;
$url = 'https://craterapp.com/downloads/check/latest/'. Setting::getSetting('version') . '?type=update';
if(env('APP_ENV') === 'development')
{
$url = 'https://craterapp.com/downloads/check/latest/'. Setting::getSetting('version') . '?type=update&is_dev=1';
} else {
$url = 'https://craterapp.com/downloads/check/latest/'. Setting::getSetting('version') . '?type=update';
}
$response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]);

View File

@ -41,10 +41,14 @@ function clean_slug($string)
* @param $money
* @return formated_money
*/
function format_money_pdf($money)
function format_money_pdf($money, $currency = null)
{
$money = $money / 100;
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', 1));
if (!$currency) {
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', 1));
}
$format_money = number_format(
$money,
$currency->precision,

26
app/Unit.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace Crater;
use Illuminate\Database\Eloquent\Model;
use Crater\Item;
class Unit extends Model
{
protected $fillable = ['name', 'company_id'];
public function items()
{
return $this->hasMany(Item::class);
}
public function company()
{
return $this->belongsTo(Company::class);
}
public function scopeWhereCompany($query, $company_id)
{
$query->where('company_id', $company_id);
}
}

View File

@ -1,4 +1,4 @@
<?php
<?php
return [

View File

@ -9,6 +9,6 @@ return [
|
*/
'version' => '2.0.1',
'version' => '3.0.0',
];

244
config/dompdf.php Normal file
View File

@ -0,0 +1,244 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Settings
|--------------------------------------------------------------------------
|
| Set some default values. It is possible to add all defines that can be set
| in dompdf_config.inc.php. You can also override the entire config file.
|
*/
'show_warnings' => false, // Throw an Exception on warnings from dompdf
'orientation' => 'portrait',
'defines' => array(
/**
* The location of the DOMPDF font directory
*
* The location of the directory where DOMPDF will store fonts and font metrics
* Note: This directory must exist and be writable by the webserver process.
* *Please note the trailing slash.*
*
* Notes regarding fonts:
* Additional .afm font metrics can be added by executing load_font.php from command line.
*
* Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
* be embedded in the pdf file or the PDF may not display correctly. This can significantly
* increase file size unless font subsetting is enabled. Before embedding a font please
* review your rights under the font license.
*
* Any font specification in the source HTML is translated to the closest font available
* in the font directory.
*
* The pdf standard "Base 14 fonts" are:
* Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
* Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
* Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
* Symbol, ZapfDingbats.
*/
"font_dir" => storage_path('fonts/'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
/**
* The location of the DOMPDF font cache directory
*
* This directory contains the cached font metrics for the fonts used by DOMPDF.
* This directory can be the same as DOMPDF_FONT_DIR
*
* Note: This directory must exist and be writable by the webserver process.
*/
"font_cache" => storage_path('fonts/'),
/**
* The location of a temporary directory.
*
* The directory specified must be writeable by the webserver process.
* The temporary directory is required to download remote images and when
* using the PFDLib back end.
*/
"temp_dir" => sys_get_temp_dir(),
/**
* ==== IMPORTANT ====
*
* dompdf's "chroot": Prevents dompdf from accessing system files or other
* files on the webserver. All local files opened by dompdf must be in a
* subdirectory of this directory. DO NOT set it to '/' since this could
* allow an attacker to use dompdf to read any files on the server. This
* should be an absolute path.
* This is only checked on command line call by dompdf.php, but not by
* direct class use like:
* $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
*/
"chroot" => realpath(base_path()),
/**
* Whether to enable font subsetting or not.
*/
"enable_font_subsetting" => false,
/**
* The PDF rendering backend to use
*
* Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
* 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
* fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
* Canvas_Factory} ultimately determines which rendering class to instantiate
* based on this setting.
*
* Both PDFLib & CPDF rendering backends provide sufficient rendering
* capabilities for dompdf, however additional features (e.g. object,
* image and font support, etc.) differ between backends. Please see
* {@link PDFLib_Adapter} for more information on the PDFLib backend
* and {@link CPDF_Adapter} and lib/class.pdf.php for more information
* on CPDF. Also see the documentation for each backend at the links
* below.
*
* The GD rendering backend is a little different than PDFLib and
* CPDF. Several features of CPDF and PDFLib are not supported or do
* not make any sense when creating image files. For example,
* multiple pages are not supported, nor are PDF 'objects'. Have a
* look at {@link GD_Adapter} for more information. GD support is
* experimental, so use it at your own risk.
*
* @link http://www.pdflib.com
* @link http://www.ros.co.nz/pdf
* @link http://www.php.net/image
*/
"pdf_backend" => "CPDF",
/**
* PDFlib license key
*
* If you are using a licensed, commercial version of PDFlib, specify
* your license key here. If you are using PDFlib-Lite or are evaluating
* the commercial version of PDFlib, comment out this setting.
*
* @link http://www.pdflib.com
*
* If pdflib present in web server and auto or selected explicitely above,
* a real license code must exist!
*/
//"DOMPDF_PDFLIB_LICENSE" => "your license key here",
/**
* html target media view which should be rendered into pdf.
* List of types and parsing rules for future extensions:
* http://www.w3.org/TR/REC-html40/types.html
* screen, tty, tv, projection, handheld, print, braille, aural, all
* Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
* Note, even though the generated pdf file is intended for print output,
* the desired content might be different (e.g. screen or projection view of html file).
* Therefore allow specification of content here.
*/
"default_media_type" => "screen",
/**
* The default paper size.
*
* North America standard is "letter"; other countries generally "a4"
*
* @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
*/
"default_paper_size" => "a4",
/**
* The default font family
*
* Used if no suitable fonts can be found. This must exist in the font folder.
* @var string
*/
"default_font" => "DejaVu Sans",
/**
* Image DPI setting
*
* This setting determines the default DPI setting for images and fonts. The
* DPI may be overridden for inline images by explictly setting the
* image's width & height style attributes (i.e. if the image's native
* width is 600 pixels and you specify the image's width as 72 points,
* the image will have a DPI of 600 in the rendered PDF. The DPI of
* background images can not be overridden and is controlled entirely
* via this parameter.
*
* For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
* If a size in html is given as px (or without unit as image size),
* this tells the corresponding size in pt.
* This adjusts the relative sizes to be similar to the rendering of the
* html page in a reference browser.
*
* In pdf, always 1 pt = 1/72 inch
*
* Rendering resolution of various browsers in px per inch:
* Windows Firefox and Internet Explorer:
* SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
* Linux Firefox:
* about:config *resolution: Default:96
* (xorg screen dimension in mm and Desktop font dpi settings are ignored)
*
* Take care about extra font/image zoom factor of browser.
*
* In images, <img> size in pixel attribute, img css style, are overriding
* the real image dimension in px for rendering.
*
* @var int
*/
"dpi" => 96,
/**
* Enable inline PHP
*
* If this setting is set to true then DOMPDF will automatically evaluate
* inline PHP contained within <script type="text/php"> ... </script> tags.
*
* Enabling this for documents you do not trust (e.g. arbitrary remote html
* pages) is a security risk. Set this option to false if you wish to process
* untrusted documents.
*
* @var bool
*/
"enable_php" => false,
/**
* Enable inline Javascript
*
* If this setting is set to true then DOMPDF will automatically insert
* JavaScript code contained within <script type="text/javascript"> ... </script> tags.
*
* @var bool
*/
"enable_javascript" => true,
/**
* Enable remote file access
*
* If this setting is set to true, DOMPDF will access remote sites for
* images and CSS files as required.
* This is required for part of test case www/test/image_variants.html through www/examples.php
*
* Attention!
* This can be a security risk, in particular in combination with DOMPDF_ENABLE_PHP and
* allowing remote access to dompdf.php or on allowing remote html code to be passed to
* $dompdf = new DOMPDF(, $dompdf->load_html(...,
* This allows anonymous users to download legally doubtful internet content which on
* tracing back appears to being downloaded by your server, or allows malicious php code
* in remote html pages to be executed by your server with your account privileges.
*
* @var bool
*/
"enable_remote" => true,
/**
* A ratio applied to the fonts height to be more like browsers' line height
*/
"font_height_ratio" => 1.1,
/**
* Use the more-than-experimental HTML5 Lib parser
*/
"enable_html5_parser" => true,
),
);

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUnitsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('units', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('units');
}
}

View File

@ -21,6 +21,8 @@ class CreateItemsTable extends Migration
$table->unsignedBigInteger('price');
$table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->integer('unit_id')->unsigned()->nullable();
$table->foreign('unit_id')->references('id')->on('units')->onDelete('cascade');
$table->timestamps();
});
}

View File

@ -30,6 +30,6 @@ class CreateExpenseCategoriesTable extends Migration
*/
public function down()
{
Schema::dropIfExists('expenses_categories');
Schema::dropIfExists('expense_categories');
}
}

View File

@ -39,6 +39,6 @@ class CreateAddressesTable extends Migration
*/
public function down()
{
Schema::dropIfExists('address');
Schema::dropIfExists('addresses');
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePaymentMethodsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('payment_methods', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('payment_methods');
}
}

View File

@ -16,16 +16,18 @@ class CreatePaymentsTable extends Migration
Schema::create('payments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('payment_number');
$table->string('payment_mode')->nullable();
$table->date('payment_date');
$table->text('notes')->nullable();
$table->unsignedBigInteger('amount');
$table->string('unique_hash')->nullable();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('invoice_id')->unsigned()->nullable();
$table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
$table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
$table->integer('payment_method_id')->unsigned()->nullable();
$table->foreign('payment_method_id')->references('id')->on('payment_methods')->onDelete('cascade');
$table->timestamps();
});
}

View File

@ -20,9 +20,9 @@ class CreateMediaTable extends Migration
$table->string('mime_type')->nullable();
$table->string('disk');
$table->unsignedInteger('size');
$table->json('manipulations');
$table->json('custom_properties');
$table->json('responsive_images');
$table->text('manipulations');
$table->text('custom_properties');
$table->text('responsive_images');
$table->unsignedInteger('order_column')->nullable();
$table->nullableTimestamps();
});

View File

@ -524,6 +524,14 @@ class CurrenciesTableSeeder extends Seeder
'thousand_separator' => '.',
'decimal_separator' => ','
],
[
'name' => 'Serbian Dinar',
'code' => 'RSD',
'symbol' => 'RSD',
'precision' => '2',
'thousand_separator' => '.',
'decimal_separator' => ','
],
];
foreach ($currencies as $currency) {

View File

@ -0,0 +1,20 @@
<?php
use Illuminate\Database\Seeder;
use Crater\PaymentMethod;
class PaymentMethodSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
PaymentMethod::create(['name' => 'Cash', 'company_id' => 1]);
PaymentMethod::create(['name' => 'Check', 'company_id' => 1]);
PaymentMethod::create(['name' => 'Credit Card', 'company_id' => 1]);
PaymentMethod::create(['name' => 'Bank Transfer', 'company_id' => 1]);
}
}

View File

@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Seeder;
use Crater\Unit;
class UnitSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Unit::create(['name' => 'box', 'company_id' => 1]);
Unit::create(['name' => 'cm', 'company_id' => 1]);
Unit::create(['name' => 'dz', 'company_id' => 1]);
Unit::create(['name' => 'ft', 'company_id' => 1]);
Unit::create(['name' => 'g', 'company_id' => 1]);
Unit::create(['name' => 'in', 'company_id' => 1]);
Unit::create(['name' => 'kg', 'company_id' => 1]);
Unit::create(['name' => 'km', 'company_id' => 1]);
Unit::create(['name' => 'lb', 'company_id' => 1]);
Unit::create(['name' => 'mg', 'company_id' => 1]);
Unit::create(['name' => 'pc', 'company_id' => 1]);
}
}

View File

@ -0,0 +1,40 @@
version: '3.1'
services:
web:
image: nginx
depends_on:
- php
ports:
- 8080:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- app:/app
restart: always
php:
build: .
depends_on:
- db
expose:
- 9000
volumes:
- app:/app
restart: always
db:
image: mariadb
restart: always
volumes:
- db:/var/lib/mysql
environment:
MYSQL_USER: crater
MYSQL_PASSWORD: crater
MYSQL_DATABASE: crater
MYSQL_ROOT_PASSWORD: crater
volumes:
app:
db:

53
nginx.conf Normal file
View File

@ -0,0 +1,53 @@
worker_processes 8;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80 default_server;
root /app/public;
index index.php;
charset utf-8;
access_log off;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header Content-Security-Policy "frame-ancestors 'self'";
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
}

15
package-lock.json generated
View File

@ -17428,6 +17428,16 @@
"resolved": "https://registry.npmjs.org/v-money/-/v-money-0.8.1.tgz",
"integrity": "sha512-raz87AP5F2YEpv1GAocI3SC/y9af1+TQeZQIhAK5UNovho6dnh6RQBa5UG8ZNC+BPLpUh5VECi7EWTjr4+4s1g=="
},
"v-tooltip": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/v-tooltip/-/v-tooltip-2.0.2.tgz",
"integrity": "sha512-xQ+qzOFfywkLdjHknRPgMMupQNS8yJtf9Utd5Dxiu/0n4HtrxqsgDtN2MLZ0LKbburtSAQgyypuE/snM8bBZhw==",
"requires": {
"lodash": "^4.17.11",
"popper.js": "^1.15.0",
"vue-resize": "^0.4.5"
}
},
"v8-compile-cache": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
@ -17515,6 +17525,11 @@
"resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.6.tgz",
"integrity": "sha512-s7jmZPlm9FeueJg1RwJtnE9KNPtME/7C8uRWSfp9/yEN4M8XcS/d+bddoyVwVnvFyRh9msFo0HWeW0vTL8Qv+w=="
},
"vue-resize": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz",
"integrity": "sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg=="
},
"vue-router": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-2.7.0.tgz",

View File

@ -48,6 +48,7 @@
"toastr": "^2.1.4",
"upgrade": "^1.1.0",
"v-money": "^0.8.1",
"v-tooltip": "^2.0.2",
"vue": "^2.5.17",
"vue-avatar-cropper": "^1.0.5",
"vue-i18n": "^8.14.0",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
{
"/assets/js/app.js": "/assets/js/app.js?id=2a5cfd8271e10bd501dc",
"/assets/css/crater.css": "/assets/css/crater.css?id=108e3a8d009e7d38018c"
"/assets/js/app.js": "/assets/js/app.js?id=397e57d36ef22a2e14fc",
"/assets/css/crater.css": "/assets/css/crater.css?id=616996a79c1df69d18de"
}

View File

@ -29,7 +29,7 @@ Web Application is made using Laravel & VueJS while the Mobile Apps are built us
## Mobile Apps
- [Android](https://play.google.com/store/apps/details?id=com.craterapp.app)
- IOS - Coming Soon
- [IOS](https://apps.apple.com/app/id1489169767)
- [Source](https://github.com/bytefury/crater-mobile)
## Discord
@ -60,8 +60,14 @@ Join the Crater discord server to discuss:
## Credits
Crater is a product of [Bytefury](https://bytefury.com)
**Special thanks to:**
* [Birkhoff Lee](https://github.com/BirkhoffLee)
* [Hassan A. Ba Abdullah](https://github.com/hsnapps)
## Translate
Help us translate on [Transifex](https://www.transifex.com/bytefury/crater-invoice)
Help us translate or suggest changes to existing languages if you find any mistakes by creating a new PR.
Here's the [english-version](https://github.com/bytefury/crater/blob/master/resources/assets/js/plugins/en.json) json file which you can use as a reference.
## License
Crater is released under the Attribution Assurance License.

View File

@ -12,6 +12,7 @@ import CustomerModal from './components/base/modal/CustomerModal.vue'
import TaxTypeModal from './components/base/modal/TaxTypeModal.vue'
import CategoryModal from './components/base/modal/CategoryModal.vue'
import money from 'v-money'
import VTooltip from 'v-tooltip'
/**
* Global css plugins
@ -107,6 +108,7 @@ window.toastr = require('toastr')
Vue.use(VueRouter)
Vue.use(Vuex)
Vue.use(VTooltip)
// register directive v-money and component <money>
Vue.use(money, {precision: 2})

View File

@ -0,0 +1,71 @@
<template>
<div class="base-prefix-input" @click="focusInput">
<font-awesome-icon v-if="icon" :icon="icon" class="icon" />
<p class="prefix-label"><span class="mr-1">{{ prefix }}</span>-</p>
<input
ref="basePrefixInput"
v-model="inputValue"
:type="type"
class="prefix-input-field"
@input="handleInput"
@change="handleChange"
@keyup="handleKeyupEnter"
@keydown="handleKeyDownEnter"
@blur="handleFocusOut"
>
</div>
</template>
<script>
export default {
props: {
prefix: {
type: String,
default: null,
required: true
},
icon: {
type: String,
default: null
},
value: {
type: [String, Number, File],
default: ''
},
type: {
type: String,
default: 'text'
}
},
data () {
return {
inputValue: this.value
}
},
watch: {
'value' () {
this.inputValue = this.value
}
},
methods: {
focusInput () {
this.$refs.basePrefixInput.focus()
},
handleInput (e) {
this.$emit('input', this.inputValue)
},
handleChange (e) {
this.$emit('change', this.inputValue)
},
handleKeyupEnter (e) {
this.$emit('keyup', this.inputValue)
},
handleKeyDownEnter (e) {
this.$emit('keydown', e, this.inputValue)
},
handleFocusOut (e) {
this.$emit('blur', this.inputValue)
}
}
}
</script>

View File

@ -8,6 +8,7 @@ import BaseTextArea from './BaseTextArea.vue'
import BaseSelect from './base-select/BaseSelect.vue'
import BaseLoader from './BaseLoader.vue'
import BaseCustomerSelect from './BaseCustomerSelect.vue'
import BasePrefixInput from './BasePrefixInput.vue'
import BasePopup from './popup/BasePopup.vue'
import CustomerSelectPopup from './popup/CustomerSelectPopup.vue'
@ -23,6 +24,7 @@ Vue.component('base-input', BaseInput)
Vue.component('base-switch', BaseSwitch)
Vue.component('base-text-area', BaseTextArea)
Vue.component('base-loader', BaseLoader)
Vue.component('base-prefix-input', BasePrefixInput)
Vue.component('table-component', TableComponent)
Vue.component('table-column', TableColumn)

View File

@ -21,6 +21,9 @@ import EstimateTemplate from './EstimateTemplate'
import InvoiceTemplate from './InvoiceTemplate'
import CustomerModal from './CustomerModal'
import CategoryModal from './CategoryModal'
import PaymentMode from './PaymentModeModal'
import ItemUnit from './ItemUnitModal'
import MailTestModal from './MailTestModal'
export default {
components: {
@ -29,7 +32,10 @@ export default {
EstimateTemplate,
InvoiceTemplate,
CustomerModal,
CategoryModal
CategoryModal,
PaymentMode,
ItemUnit,
MailTestModal
},
data () {
return {

View File

@ -55,6 +55,7 @@
v-model="currency"
:options="currencies"
:searchable="true"
:allow-empty="false"
:show-labels="false"
:placeholder="$t('customers.select_currency')"
label="name"
@ -340,6 +341,7 @@ export default {
mixins: [validationMixin],
data () {
return {
isEdit: false,
isLoading: false,
countryList: [],
billingCountry: null,
@ -398,9 +400,22 @@ export default {
...mapGetters('currency', [
'defaultCurrency',
'currencies'
]),
...mapGetters('modal', [
'modalDataID',
'modalData',
'modalActive'
])
},
watch: {
'modalDataID' (val) {
if (val) {
this.isEdit = true
this.setData()
} else {
this.isEdit = false
}
},
billingCountry () {
if (this.billingCountry) {
this.billing.country_id = this.billingCountry.id
@ -418,6 +433,9 @@ export default {
this.$refs.name.focus = true
this.currency = this.defaultCurrency
this.fetchCountry()
if (this.modalDataID) {
this.setData()
}
},
methods: {
...mapActions('invoice', {
@ -492,6 +510,24 @@ export default {
this.formData.addresses = [{...this.shipping, type: 'shipping'}]
return true
},
async setData () {
this.formData.id = this.modalData.id
this.formData.name = this.modalData.name
this.formData.email = this.modalData.email
this.formData.contact_name = this.modalData.contact_name
this.formData.phone = this.modalData.phone
this.formData.website = this.modalData.website
this.currency = this.modalData.currency
if (this.modalData.billing_address) {
this.billing = this.modalData.billing_address
this.billingCountry = this.modalData.billing_address.country
}
if (this.modalData.shipping_address) {
this.shipping = this.modalData.shipping_address
this.shippingCountry = this.modalData.shipping_address.country
}
},
async submitCustomerData () {
this.$v.formData.$touch()
@ -509,14 +545,23 @@ export default {
this.formData.currency_id = this.defaultCurrency.id
}
try {
let response = await this.addCustomer(this.formData)
let response = null
if (this.modalDataID) {
response = await this.updateCustomer(this.formData)
} else {
response = await this.addCustomer(this.formData)
}
if (response.data) {
window.toastr['success'](this.$tc('customers.created_message'))
if (this.modalDataID) {
window.toastr['success'](this.$tc('customers.updated_message'))
} else {
window.toastr['success'](this.$tc('customers.created_message'))
}
this.isLoading = false
if (this.$route.name === 'invoices.create') {
if (this.$route.name === 'invoices.create' || this.$route.name === 'invoices.edit') {
this.setInvoiceCustomer(response.data.customer.id)
}
if (this.$route.name === 'estimates.create') {
if (this.$route.name === 'estimates.create' || this.$route.name === 'estimates.edit') {
this.setEstimateCustomer(response.data.customer.id)
}
this.resetData()

View File

@ -45,14 +45,34 @@
<div class="col-sm-7">
<base-select
v-model="formData.unit"
:options="units"
:options="itemUnits"
:searchable="true"
:show-labels="false"
label="name"
>
<div slot="afterList">
<button type="button" class="list-add-button" @click="addItemUnit">
<font-awesome-icon class="icon" icon="cart-plus" />
<label>{{ $t('settings.customization.items.add_item_unit') }}</label>
</button>
</div>
</base-select>
</div>
</div>
<div v-if="isTexPerItem" class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('items.taxes') }}</label>
<div class="col-sm-7">
<base-select
v-model="formData.taxes"
:options="getTaxTypes"
:searchable="true"
:show-labels="false"
:allow-empty="true"
:multiple="true"
label="tax_name"
/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('items.description') }}</label>
<div class="col-sm-7">
@ -124,11 +144,13 @@ export default {
{ name: 'mg', value: 'mg' },
{ name: 'pc', value: 'pc' }
],
taxes: [],
formData: {
name: null,
price: null,
description: null,
unit: null
unit: null,
taxes: []
}
}
},
@ -161,12 +183,28 @@ export default {
this.formData.price = newValue * 100
}
},
// itemUnits () {
// return this.units
// },
...mapGetters('modal', [
'modalDataID'
'modalDataID',
'modalData'
]),
...mapGetters('item', [
'getItemById'
])
'getItemById',
'itemUnits'
]),
...mapGetters('taxType', [
'taxTypes'
]),
isTexPerItem () {
return this.modalData.taxPerItem === 'YES'
},
getTaxTypes () {
return this.taxTypes.map(tax => {
return {...tax, tax_name: tax.name + ' (' + tax.percent + '%)'}
})
}
},
watch: {
modalDataID () {
@ -179,12 +217,17 @@ export default {
this.isEdit = true
this.fetchEditData()
}
if (this.isEdit) {
this.loadEditData()
}
},
mounted () {
this.$refs.name.focus = true
},
methods: {
...mapActions('modal', [
'openModal',
'closeModal',
'resetModalData'
]),
@ -203,7 +246,6 @@ export default {
unit: null,
id: null
}
this.$v.$reset()
},
fetchEditData () {
@ -230,9 +272,20 @@ export default {
if (this.isEdit) {
response = await this.updateItem(this.formData)
} else {
response = await this.addItem(this.formData)
let data = {
...this.formData,
taxes: this.formData.taxes.map(tax => {
return {
tax_type_id: tax.id,
amount: ((this.formData.price * tax.percent) / 100),
percent: tax.percent,
name: tax.name,
collective_tax: 0
}
})
}
response = await this.addItem(data)
}
if (response.data) {
window.toastr['success'](this.$tc('items.created_message'))
this.setItem(response.data.item)
@ -245,6 +298,12 @@ export default {
}
window.toastr['error'](response.data.error)
},
async addItemUnit () {
this.openModal({
'title': 'Add Item Unit',
'componentName': 'ItemUnit'
})
},
closeItemModal () {
this.resetFormData()
this.closeModal()

View File

@ -0,0 +1,148 @@
<template>
<div class="item-unit-modal">
<form action="" @submit.prevent="submitItemUnit">
<div class="card-body">
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('settings.customization.items.unit_name') }} <span class="required"> *</span></label>
<div class="col-sm-7">
<base-input
ref="name"
:invalid="$v.formData.name.$error"
v-model="formData.name"
type="text"
@input="$v.formData.name.$touch()"
/>
<div v-if="$v.formData.name.$error">
<span v-if="!$v.formData.name.required" class="form-group__message text-danger">{{ $tc('validation.required') }}</span>
</div>
</div>
</div>
</div>
<div class="card-footer">
<base-button
:outline="true"
class="mr-3"
color="theme"
type="button"
@click="closePaymentModeModal"
>
{{ $t('general.cancel') }}
</base-button>
<base-button
:loading="isLoading"
color="theme"
icon="save"
type="submit"
>
{{ !isEdit ? $t('general.save') : $t('general.update') }}
</base-button>
</div>
</form>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { validationMixin } from 'vuelidate'
const { required, minLength } = require('vuelidate/lib/validators')
export default {
mixins: [validationMixin],
data () {
return {
isEdit: false,
isLoading: false,
formData: {
id: null,
name: null
}
}
},
computed: {
...mapGetters('modal', [
'modalDataID',
'modalData',
'modalActive'
])
},
validations: {
formData: {
name: {
required,
minLength: minLength(2)
}
}
},
async mounted () {
this.$refs.name.focus = true
if (this.modalDataID) {
this.isEdit = true
this.setData()
}
},
methods: {
...mapActions('modal', [
'closeModal',
'resetModalData'
]),
...mapActions('item', [
'addItemUnit',
'updateItemUnit',
'fatchItemUnit'
]),
resetFormData () {
this.formData = {
id: null,
name: null
}
this.$v.formData.$reset()
},
async submitItemUnit () {
this.$v.formData.$touch()
if (this.$v.$invalid) {
return true
}
this.isLoading = true
let response
if (this.isEdit) {
response = await this.updateItemUnit(this.formData)
if (response.data) {
window.toastr['success'](this.$t('settings.customization.items.item_unit_updated'))
this.closePaymentModeModal()
return true
}
window.toastr['error'](response.data.error)
} else {
try {
response = await this.addItemUnit(this.formData)
if (response.data) {
this.isLoading = false
window.toastr['success'](this.$t('settings.customization.items.item_unit_added'))
this.closePaymentModeModal()
return true
} window.toastr['error'](response.data.error)
} catch (err) {
if (err.response.data.errors.name) {
this.isLoading = true
window.toastr['error'](this.$t('validation.item_unit_already_taken'))
}
}
}
},
async setData () {
this.formData = {
id: this.modalData.id,
name: this.modalData.name
}
},
closePaymentModeModal () {
this.resetModalData()
this.resetFormData()
this.closeModal()
}
}
}
</script>

View File

@ -0,0 +1,166 @@
<template>
<div class="mail-test-modal">
<form action="" @submit.prevent="onTestMailSend">
<div class="card-body">
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('general.to') }} <span class="required"> *</span></label>
<div class="col-sm-7">
<base-input
ref="to"
:invalid="$v.formData.to.$error"
v-model="formData.to"
type="text"
@input="$v.formData.to.$touch()"
/>
<div v-if="$v.formData.to.$error">
<span v-if="!$v.formData.to.required" class="form-group__message text-danger">{{ $tc('validation.required') }}</span>
<span v-if="!$v.formData.to.email" class="form-group__message text-danger"> {{ $t('validation.email_incorrect') }} </span>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('general.subject') }} <span class="required"> *</span></label>
<div class="col-sm-7">
<div class="base-input">
<base-input
:invalid="$v.formData.subject.$error"
v-model="formData.subject"
type="text"
@input="$v.formData.subject.$touch()"
/>
</div>
<div v-if="$v.formData.subject.$error">
<span v-if="!$v.formData.subject.required" class="text-danger">{{ $t('validation.required') }}</span>
<span v-if="!$v.formData.subject.maxLength" class="text-danger">{{ $t('validation.subject_maxlength') }}</span>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('general.message') }}<span class="required"> *</span></label>
<div class="col-sm-7">
<base-text-area
v-model="formData.message"
:invalid="$v.formData.message.$error"
rows="4"
cols="50"
@input="$v.formData.message.$touch()"
/>
<div v-if="$v.formData.message.$error">
<span v-if="!$v.formData.message.required" class="text-danger">{{ $t('validation.required') }}</span>
<span v-if="!$v.formData.message.maxLength" class="text-danger">{{ $t('validation.message_maxlength') }}</span>
</div>
</div>
</div>
</div>
<div class="card-footer">
<base-button
:outline="true"
class="mr-3"
color="theme"
type="button"
@click="closeTaxModal"
>
{{ $t('general.cancel') }}
</base-button>
<base-button
:loading="isLoading"
color="theme"
icon="save"
type="submit"
>
{{ !isEdit ? $t('general.save') : $t('general.update') }}
</base-button>
</div>
</form>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { validationMixin } from 'vuelidate'
const { required, minLength, email, maxLength } = require('vuelidate/lib/validators')
export default {
mixins: [validationMixin],
data () {
return {
isEdit: false,
isLoading: false,
formData: {
to: null,
subject: null,
message: null
}
}
},
computed: {
...mapGetters('modal', [
'modalDataID',
'modalData',
'modalActive'
])
},
validations: {
formData: {
to: {
required,
email
},
subject: {
required,
maxLength: maxLength(100)
},
message: {
required,
maxLength: maxLength(255)
}
}
},
async mounted () {
this.$refs.to.focus = true
},
methods: {
...mapActions('modal', [
'closeModal',
'resetModalData'
]),
resetFormData () {
this.formData = {
to: null,
subject: null,
message: null
}
this.$v.formData.$reset()
},
async onTestMailSend () {
this.$v.formData.$touch()
if (this.$v.$invalid) {
return true
}
this.isLoading = true
let response = await axios.post('/api/settings/test/mail', this.formData)
if (response.data) {
if (response.data.success) {
window.toastr['success'](this.$tc('general.send_mail_successfully'))
this.closeTaxModal()
this.isLoading = false
return true
}
window.toastr['error'](this.$tc('validation.something_went_wrong'))
this.closeTaxModal()
this.isLoading = false
return true
}
window.toastr['error'](response.data.error)
},
closeTaxModal () {
this.resetModalData()
this.resetFormData()
this.closeModal()
}
}
}
</script>

View File

@ -0,0 +1,143 @@
<template>
<div class="payment-modes-modal">
<form action="" @submit.prevent="submitPaymentMode">
<div class="card-body">
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('settings.customization.payments.mode_name') }} <span class="required"> *</span></label>
<div class="col-sm-7">
<base-input
ref="name"
:invalid="$v.formData.name.$error"
v-model="formData.name"
type="text"
@input="$v.formData.name.$touch()"
/>
<div v-if="$v.formData.name.$error">
<span v-if="!$v.formData.name.required" class="form-group__message text-danger">{{ $tc('validation.required') }}</span>
</div>
</div>
</div>
</div>
<div class="card-footer">
<base-button
:outline="true"
class="mr-3"
color="theme"
type="button"
@click="closePaymentModeModal"
>
{{ $t('general.cancel') }}
</base-button>
<base-button
:loading="isLoading"
color="theme"
icon="save"
type="submit"
>
{{ !isEdit ? $t('general.save') : $t('general.update') }}
</base-button>
</div>
</form>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { validationMixin } from 'vuelidate'
const { required, minLength } = require('vuelidate/lib/validators')
export default {
mixins: [validationMixin],
data () {
return {
isEdit: false,
isLoading: false,
formData: {
id: null,
name: null
}
}
},
computed: {
...mapGetters('modal', [
'modalDataID',
'modalData',
'modalActive'
])
},
validations: {
formData: {
name: {
required,
minLength: minLength(2)
}
}
},
async mounted () {
this.$refs.name.focus = true
if (this.modalDataID) {
this.isEdit = true
this.setData()
}
},
methods: {
...mapActions('modal', [
'closeModal',
'resetModalData'
]),
...mapActions('payment', [
'addPaymentMode',
'updatePaymentMode'
]),
resetFormData () {
this.formData = {
id: null,
name: null
}
this.$v.formData.$reset()
},
async submitPaymentMode () {
this.$v.formData.$touch()
if (this.$v.$invalid) {
return true
}
this.isLoading = true
let response
if (this.isEdit) {
response = await this.updatePaymentMode(this.formData)
if (response.data) {
window.toastr['success'](this.$t('settings.customization.payments.payment_mode_updated'))
this.closePaymentModeModal()
return true
} window.toastr['error'](response.data.error)
} else {
try {
response = await this.addPaymentMode(this.formData)
if (response.data) {
this.isLoading = false
window.toastr['success'](this.$t('settings.customization.payments.payment_mode_added'))
this.closePaymentModeModal()
return true
} window.toastr['error'](response.data.error)
} catch (err) {
if (err.response.data.errors.name) {
this.isLoading = true
window.toastr['error'](this.$t('validation.payment_mode_already_taken'))
}
}
}
},
async setData () {
this.formData = {
id: this.modalData.id,
name: this.modalData.name
}
},
closePaymentModeModal () {
this.resetModalData()
this.resetFormData()
this.closeModal()
}
}
}
</script>

View File

@ -124,7 +124,7 @@ export default {
},
percent: {
required,
between: between(0.10, 100)
between: between(0, 100)
},
description: {
maxLength: maxLength(255)

View File

@ -0,0 +1,883 @@
{
"navigation": {
"dashboard": "الرئيسية",
"customers": "العملاء",
"items": "الأصناف",
"invoices": "الفواتير",
"expenses": "النفقات",
"estimates": "التقديرات",
"payments": "المدفوعات",
"reports": "التقارير",
"settings": "الإعدادات",
"logout": "خروج"
},
"general": {
"view_pdf": "عرض PDF",
"download_pdf": "تنزيل PDF",
"save": "حفظ",
"cancel": "إلغاء الأمر",
"update": "تحديث",
"download": "تنزيل",
"from_date": "من تاريخ",
"to_date": "إلى تاريخ",
"from": "من",
"to": "إلى",
"go_back": "إلى الخلف",
"back_to_login": "العودة إلى تسجيل الدخول؟",
"home": "الرئيسية",
"filter": "تصفية",
"delete": "حذف",
"edit": "تعديل",
"view": "عرض",
"add_new_item": "إضافة صنف جديد",
"clear_all": "مسح الكل",
"showing": "عرض",
"of": "من",
"actions": "العمليات",
"subtotal": "المجموع الفرعي",
"discount": "خصم",
"fixed": "ثابت",
"percentage": "نسبة",
"tax": "ضريبة",
"total_amount": "المبلغ الإجمالي",
"bill_to": "مطلوب من",
"ship_to": "يشحن إلى",
"due": "واجبة السداد",
"draft": "مسودة",
"sent": "مرسلة",
"all": "الكل",
"select_all": "تحديد الل",
"choose_file": "اضغط هنا لاختيار ملف",
"choose_template": "اختيار القالب",
"choose": "اختر",
"remove": "إزالة",
"powered_by": "تصميم",
"bytefury": "باترفوري",
"select_a_status": "اختر الحالة",
"select_a_tax": "اختر الضريبة",
"search": "بحث",
"are_you_sure": "هل أنت متأكد?",
"list_is_empty": "القائمة فارغة.",
"no_tax_found": "لا يوجد ضريبة!",
"four_zero_four": "404",
"you_got_lost": "عفواً! يبدو أنك قد تهت!",
"go_home": "عودة إلى الرئيسية",
"setting_updated": "تم تحديث الإعدادات بنجاح",
"select_state": "اختر الولاية/المنطقة",
"select_country": "اختر الدولة",
"select_city": "اختر المدينة",
"street_1": "عنوان الشارع 1",
"street_2": "عنوان الشارع 2",
"action_failed": "فشلت العملية"
},
"dashboard": {
"select_year": "اختر السنة",
"cards": {
"due_amount": "المبلغ المطلوب",
"customers": "العملاء",
"invoices": "الفواتير",
"estimates": "التقديرات"
},
"chart_info": {
"total_sales": "المبيعات",
"total_receipts": "إجمالي الدخل",
"total_expense": "النفقات",
"net_income": "صافي الدخل",
"year": "اختر السنة"
},
"weekly_invoices": {
"title": "الفواتير الأسبوعية"
},
"monthly_chart": {
"title": "المبيعات والنفقات"
},
"recent_invoices_card": {
"title": "فواتير مستحقة",
"due_on": "مستحقة في",
"customer": "العميل",
"amount_due": "المبلغ المطلوب",
"actions": "العمليات",
"view_all": "عرض الكل"
},
"recent_estimate_card": {
"title": "أحدث التقديرات",
"date": "التاريخ",
"customer": "العميل",
"amount_due": "المبلغ المطلوب",
"actions": "العمليات",
"view_all": "عرض الكل"
}
},
"tax_types": {
"name": "الاسم",
"description": "الوصف",
"percent": "Percent",
"compound_tax": "Compound Tax"
},
"customers": {
"title": "العملاء",
"add_customer": "إضافة عميل",
"contacts_list": "قائمة العملاء",
"name": "الاسم",
"display_name": "اسم العرض",
"primary_contact_name": "اسم التواصل الرئيسي",
"contact_name": "اسم تواصل آخر",
"amount_due": "المبلغ المطلوب",
"email": "البريد الإلكتروني",
"address": "العنوان",
"phone": "الهاتف",
"website": "موقع الإنترنت",
"country": "الدولة",
"state": "الولاية/المنطقة",
"city": "المدينة",
"zip_code": "الرمز البريدي",
"added_on": "أضيف في",
"action": "إجراء",
"password": "كلمة المرور",
"street_number": "رقم الشارع",
"primary_currency": "العملة الرئيسية",
"add_new_customer": "إضافة عميل جديد",
"save_customer": "حفظ العميل",
"update_customer": "تحديث بيانات العميل",
"customer": "عميل | عملاء",
"new_customer": "عميل جديد",
"edit_customer": "تعديل عميل",
"basic_info": "معلوات أساسية",
"billing_address": "عنوان الفوترة",
"shipping_address": "عنوان الشحن",
"copy_billing_address": "نسخ من عنوان الفوترة",
"no_customers": "لا يوجد عملاء حتى الآن!",
"no_customers_found": "لم يتم الحصول على عملاء!",
"list_of_customers": "سوف يحتوي هذا القسم على قائمة العملاء.",
"primary_display_name": "اسم العرض الرئيسي",
"select_currency": "اختر العملة",
"select_a_customer": "اختر العميل",
"type_or_click": "اكتب أو اضغط للاختيار",
"confirm_delete": "لن تكون قادراً على استرجاع هذا العميل | لن تكون قادراً على استرجاع هؤلاء العملاء",
"created_message": "تم إنشاء العملاء بنجاح",
"updated_message": "تم تحديث العملاء بنجاح",
"deleted_message": "تم حذف العملاء بنجاح | تم حذف العميل بنجاح"
},
"items": {
"title": "الأصناف",
"items_list": "قائمة الأصناف",
"name": "الاسم",
"unit": "الوحدة",
"description": "الوصف",
"added_on": "أضيف في",
"price": "السعر",
"date_of_creation": "تاريخ الإنشاء",
"action": "إجراء",
"add_item": "إضافة صنف",
"save_item": "حفظ الصنف",
"update_item": "تحديث الصنف",
"item": "صنف | أصناف",
"add_new_item": "إضافة صنف جديد",
"new_item": "جديد صنف",
"edit_item": "تحديث صنف",
"no_items": "لا يوجد أصناف حتى الآن!",
"list_of_items": "هذا القسم سوف يحتوي على قائمة الأصناف.",
"select_a_unit": "اختر الوحدة",
"item_attached_message": "لا يمكن حذف الصنف قيد الاستخدام",
"confirm_delete": "لن تتمكن من استرجاع هذا الصنف | لن تتمكن من استرجاع هذه الأصناف",
"created_message": "تم إنشاء الصنف بنجاح",
"updated_message": "تم تحديث الصنف بنجاح",
"deleted_message": "تم حذف الصنف بنجاح | تم حذف الأصناف بنجاح"
},
"estimates": {
"title": "التقديرات",
"estimate": "تقدير | تقديرات",
"estimates_list": "قائمة التقديرات",
"days": "{days} أيام",
"months": "{months} أشهر",
"years": "{years} سنوات",
"all": "الكل",
"paid": "مدفوع",
"unpaid": "غير مدفوع",
"customer": "العميل",
"ref_no": "رقم المرجع.",
"number": "الرقم",
"amount_due": "المبلغ المطلوب",
"partially_paid": "مدفوع جزئيا",
"total": "الإجمالي",
"discount": "الخصم",
"sub_total": "حاصل الجمع",
"estimate_number": "رقم تقدير",
"ref_number": "رقم المرجع",
"contact": "تواصل",
"add_item": "إضافة صنف",
"date": "تاريخ",
"due_date": "تاريخ الاستحقاق",
"expiry_date": "تاريخ الصلاحية",
"status": "الحالة",
"add_tax": "إضافة ضرية",
"amount": "المبلغ المطلوب",
"action": "إجراء",
"notes": "ملاحظات",
"tax": "ضريبة",
"estimate_template": "قالب",
"convert_to_invoice": "تحويل إلى فاتورة",
"mark_as_sent": "تحديد كمرسل",
"send_estimate": "إرسال التقدير",
"record_payment": "تسجيل مدفوات",
"add_estimate": "إضافة تقدير",
"save_estimate": "حفظ التقدير",
"confirm_conversion": "هل تريد تحويل هذا التقدير إلى فاتورة؟",
"conversion_message": "تم إنشاء الفاتورة بنجاح",
"confirm_send_estimate": "سيتم إرسال هذا التقدير بالبريد الإلكتروني إلى العميل",
"confirm_mark_as_sent": "سيتم التحديد كمرسل على هذا التقدير",
"confirm_mark_as_accepted": "سيتم التحديد كمقبول على هذا التقدير",
"confirm_mark_as_rejected": "سيتم التحديد كمرفوض على هذا التقدير",
"no_matching_estimates": "لا يوجد تقديرات مطابقة!",
"mark_as_sent_successfully": "تم التحديد كمرسل بنجاح",
"send_estimate_successfully": "تم إرسال التقدير بنجاح",
"errors": {
"required": "حقل مطلوب"
},
"accepted": "مقبول",
"sent": "مرسل",
"draft": "مسودة",
"declined": "مرفوض",
"new_estimate": "تقدير جديد",
"add_new_estimate": "إضافة تقدير جديد",
"update_Estimate": "تحديث تقدير",
"edit_estimate": "تعديل التقدير",
"items": "الأصناف",
"Estimate": "تقدير | تقديرات",
"add_new_tax": "إضافة ضريبة جديدة",
"no_estimates": "لا يوجد تقديرات حالياً!",
"list_of_estimates": "هذا القسم سوف يحتوي على التقديرات.",
"mark_as_rejected": "تحديد كمرفوض",
"mark_as_accepted": "تحديد كمقروء",
"marked_as_accepted_message": "تحديد التقدير كمقبول",
"marked_as_rejected_message": "تحديد التقدير كمرفوض",
"confirm_delete": "لن تستطيع استرجاع هذا التقدير | لن تستطيع إستعادة هذه التقديرات",
"created_message": "تم إنشاء التقدير بنجاح",
"updated_message": "تم تحديث التقدير بنجاح",
"deleted_message": "تم حذف التقدير بنجاح | تم حذف التقديرات بنجاح",
"user_email_does_not_exist": "البريد الالكتروني للمستخدم غير موجود",
"something_went_wrong": "خطأ غير معروف!",
"item": {
"title": "اسم الصنف",
"description": "الوصف",
"quantity": "الكمية",
"price": "السعر",
"discount": "الخصم",
"total": "الإجمالي",
"total_discount": "مجموع الخصم",
"sub_total": "حاصل الجمع",
"tax": "الضرية",
"amount": "المبلغ المطلوب",
"select_an_item": "اكتب أو اختر الصنف",
"type_item_description": "اكتب وصف الصنف (اختياري)"
}
},
"invoices": {
"title": "الفواتير",
"invoices_list": "قائمة الفواتير",
"days": "{days} أيام",
"months": "{months} أشهر",
"years": "{years} سنوات",
"all": "الكل",
"paid": "مدفوع",
"unpaid": "غير مدفوع",
"customer": "العميل",
"paid_status": "حالة الدفع",
"ref_no": "رقم المرجع.",
"number": "الرقم",
"amount_due": "المبلغ المطلوب",
"partially_paid": "مدفوع جزئياً",
"total": "الإجمالي",
"discount": "الخصم",
"sub_total": "حاصل الجمع",
"invoice": "فاتورة | فواتير",
"invoice_number": "رقم الفاتورة",
"ref_number": "رقم المرجع",
"contact": "تواصل",
"add_item": "إضافة صنف",
"date": "التاريخ",
"due_date": "تاريخ الاستحقاق",
"status": "الحالة",
"add_tax": "إضافة ضريبة",
"amount": "المبلغ المطلوب",
"action": "إجراء",
"notes": "ملاحظات",
"view": "عرض",
"send_invoice": "إرسال الفاتورة",
"invoice_template": "قالب الفاتورة",
"template": "قالب",
"mark_as_sent": "تحديد كمرسل",
"confirm_send_invoice": "سيتم إرسال هذه الفاتورة بالبريد الألكتروني إلى العميل",
"invoice_mark_as_sent": "سيتم تحديد هذه الفاتورة كمرسلة",
"confirm_send": "سيتم إرسال هذه الفاتورة بالبريد الألكتروني إلى العميل",
"invoice_date": "تاريخ الفاتورة",
"record_payment": "تسجيل مدفوعات",
"add_new_invoice": "إضافة فاتورة جديدة",
"update_expense": "تحديث المصروفات",
"edit_invoice": "تعديل الفاتورة",
"new_invoice": "فاتورة جديدة",
"save_invoice": "حفظ الفاتورة",
"update_invoice": "تحديث الفاتورة",
"add_new_tax": "إضافة ضريبة جديدة",
"no_invoices": "لا يوجد فواتير حتى الآن!",
"list_of_invoices": "قائمة الفواتير .",
"select_invoice": "اختر الفاتورة",
"no_matching_invoices": "لا يوجد فواتير مطابقة!",
"mark_as_sent_successfully": "تم تحديد الفاتورة كمرسلة بنجاح",
"send_invoice_successfully": "تم إرسال الفاتورة بنجاح",
"item": {
"title": "اسم الصنف",
"description": "الوصف",
"quantity": "الكمية",
"price": "السعر",
"discount": "الخصم",
"total": "الإجمالي",
"total_discount": "إجمالي الخصم",
"sub_total": "حاصل الجمع",
"tax": "الضريبة",
"amount": "المبلغ المطلوب",
"select_an_item": "اكتب أو انقر لاختيار صنف",
"type_item_description": "وصف الصنف (اختياري)"
},
"payment_attached_message": "هناك مدفوعات مرتبطة بالفعل بإحدى الفواتير المحددة. تأكد من حذف المدفوعات المرتبطة أولاً قبل حذف الفاتورة.",
"confirm_delete": "لن تتمكن من استرجاع الفاتورة بعد هذه الإجراء | لن تتمكن من استرجاع الفواتير بعد هذا الإجراء",
"created_message": "تم إنشاء الفاتورة بنجاح",
"updated_message": "تم تحديث الفاتورة بنجاح",
"deleted_message": "تم حذف الفاتورة بنجاح | تم حذف الفواتير بنجاح",
"marked_as_sent_message": "تم إرسال الفاتورة بنجاح",
"user_email_does_not_exist": "البريد الإلكتروني للمستخدم غير موجود!",
"something_went_wrong": "خطأ غير معروف!",
"invalid_due_amount_message": "المبلغ النهائي للفاتورة لا يمكن أن يكون أقل من المبلغ المطلوب لها. رجاءاً حدث الفاتورة أو قم بحذف المدفوعات المرتبطة بها للاستمرار."
},
"credit_notes": {
"title": "ملاحظات إئتمانية",
"credit_notes_list": "قائمة الملاحظات الإئتمانية",
"credit_notes": "ملاحظات إئتمانية",
"contact": "تواصل",
"date": "التاريخ",
"amount": "المبلغ المطلوب",
"action": "إجراء",
"credit_number": "الرقم الإئتماني",
"notes": "ملاحظات",
"confirm_delete": "هل تريد حفذف هذه الملاحظة الإئتمانية؟",
"item": {
"title": "اسم الصنف",
"description": "الوصف",
"quantity": "الكمية",
"price": "السعر",
"discount": "الخصم",
"total": "الإجمالي",
"total_discount": "إجمالي الخصم",
"sub_total": "حاصل الجمع",
"tax": "الضريبة"
}
},
"payments": {
"title": "المدفوعات",
"payments_list": "قائمة المدفوعات",
"record_payment": "تسجيل دفعة",
"customer": "العميل",
"date": "التاريخ",
"amount": "المبلغ المطلوب",
"action": "إجراء",
"payment_number": "رقم الدفعة",
"payment_mode": "نوع الدفعة",
"invoice": "الفاتورة",
"note": "ملاحظة",
"add_payment": "إضافة دفعة",
"new_payment": "دفعة جديدة",
"edit_payment": "تعديل الدفعة",
"view_payment": "عرض الدفعة",
"add_new_payment": "إضافة دفعة جديدة",
"save_payment": "حفظ الدفعة",
"update_payment": "تحديث الدفعة",
"payment": "دفعة | مدفوعات",
"no_payments": "لا يوجد مدفوعات حتى الآن!",
"no_matching_payments": "لا توجد مدفوعات مطابقة!",
"list_of_payments": "سوف تحتوي هذه القائمة على مدفوعات الفواتير.",
"select_payment_mode": "اختر طريقة الدفع",
"confirm_delete": "لن تكون قادر على استرجاع هذه الدفعة | لن تكون قادراً على استرجاع هذه المدفوعات",
"created_message": "تم إنشاء الدفعة بنجاح",
"updated_message": "تم تحديث الدفعة بنجاح",
"deleted_message": "تم حذف الدفعة بنجاح | تم حذف المدفوعات بنجاح",
"invalid_amount_message": "قيمة الدفعة غير صحيحة!"
},
"expenses": {
"title": "النفقات",
"expenses_list": "قائمة النفقات",
"expense_title": "Title",
"contact": "تواصل",
"category": "الفئة",
"from_date": "من تاريخ",
"to_date": "حتى تاريخ",
"expense_date": "التاريخ",
"description": "الوصف",
"receipt": "سند القبض",
"amount": "المبلغ المطلوب",
"action": "إجراء",
"note": "ملاحظة",
"category_id": "رمز الفئة",
"date": "تاريخ النفقات",
"add_expense": "أضف نفقات",
"add_new_expense": "أضف نفقات جديدة",
"save_expense": "حفظ النفقات",
"update_expense": "تحديث النفقات",
"download_receipt": "تنزيل السند",
"edit_expense": "تعديل النفقات",
"new_expense": "نفقات جديدة",
"expense": "إنفاق | نفقات",
"no_expenses": "لا يوجد نفقات حتى الآن!",
"list_of_expenses": "هذه القائمة ستحتوي النفقات الخاصة بك",
"confirm_delete": "لن تتمكن من استرجاع هذا الإنفاق | لن تتمكن من استرجاع هذه النفقات",
"created_message": "تم إنشاء النفقات بنجاح",
"updated_message": "تم تحديث النفقات بنجاح",
"deleted_message": "تم حذف النفقات بنجاح",
"categories": {
"categories_list": "قائمة الفئات",
"title": "العنوان",
"name": "الاسم",
"description": "الوصف",
"amount": "المبلغ المطلوب",
"actions": "العمليات",
"add_category": "إضافة فئمة",
"new_category": "فئة جديدة",
"category": "فئة | فئات",
"select_a_category": "اختر الفئة"
}
},
"login": {
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"forgot_password": "نسيت كلمة المرور؟",
"or_signIn_with": "أو سجل الدخول بواسطة",
"login": "دخول",
"register": "تسجيل",
"reset_password": "إعادة تعيين كلمة المرور",
"password_reset_successfully": "تم إعادة تعيين كلمة المرور بنجاح",
"enter_email": "أدخل البريد الالكتروني",
"enter_password": "أكتب كلمة المرور",
"retype_password": "أعد كتابة كلمة المرور",
"login_placeholder": "mail@example.com"
},
"reports": {
"title": "تقرير",
"from_date": "من تاريخ",
"to_date": "حتى تاريخ",
"status": "الحالة",
"paid": "مدفوع",
"unpaid": "غير مدفوع",
"download_pdf": "تنزيل PDF",
"view_pdf": "عرض PDF",
"update_report": "تحديث التقرير",
"report": "تقرير | تقارير",
"profit_loss": {
"profit_loss": "الخسائر والأرباح",
"to_date": "حتى تاريخ",
"from_date": "من تاريخ",
"date_range": "اختر مدى التاريخ"
},
"sales": {
"sales": "المبيعات",
"date_range": "اختر مدى التاريخ",
"to_date": "حتى تاريخ",
"from_date": "من تاريخ",
"report_type": "نوع التقرير"
},
"taxes": {
"taxes": "الضرائب",
"to_date": "حتى تاريخ",
"from_date": "من تاريخ",
"date_range": "اختر مدى التاريخ"
},
"errors": {
"required": "حقل مطلوب"
},
"invoices": {
"invoice": "الفاتورة",
"invoice_date": "تاريخ الفاتورة",
"due_date": "تاريخ الاستحقاق",
"amount": "المبلغ المطلوب",
"contact_name": "اسم التواصل",
"status": "الحالة"
},
"estimates": {
"estimate": "تقدير",
"estimate_date": "تاريخ التقدير",
"due_date": "مستحق بتاريخ",
"estimate_number": "رقم مستحق",
"ref_number": "رقم المرجع",
"amount": "المبلغ المطلوب",
"contact_name": "اسم التواصل",
"status": "الحالة"
},
"expenses": {
"expenses": "النفقات",
"category": "الفئة",
"date": "التاريخ",
"amount": "المبلغ المطلوب",
"to_date": "حتى تاريخ",
"from_date": "من تاريخ",
"date_range": "اختر مدى التاريخ"
}
},
"settings": {
"menu_title": {
"account_settings": "إعدادات الحساب",
"company_information": "معلومات المنشأة",
"customization": "تخصيص",
"preferences": "تفضيلات",
"notifications": "تنبيهات",
"tax_types": "نوع الضريبة",
"expense_category": "فئات النفقات",
"update_app": "تحديث النظام"
},
"title": "إعدادات",
"setting": "إعدادات | إعدادات",
"general": "عام",
"language": "اللغة",
"primary_currency": "العملة الرئيسية",
"timezone": "المنطقة الزمنية",
"date_format": "صيغة التاريخ",
"currencies": {
"title": "العملات",
"currency": "العملة | العملات",
"currencies_list": "قائمة العملات",
"select_currency": "اختر العملة",
"name": "الاسم",
"code": "المرجع",
"symbol": "الرمز",
"precision": "الدقة",
"thousand_separator": "فاصل الآلاف",
"decimal_separator": "الفاصلة العشرية",
"position": "الموقع",
"position_of_symbol": "موقع رمز العملة",
"right": "يمين",
"left": "يسار",
"action": "إجراء",
"add_currency": "أضف عملة"
},
"mail": {
"host": "خادم البريد",
"port": "منفذ البريد",
"driver": "مشغل البريد",
"secret": "سري",
"mailgun_secret": "الرمز السري لـ Mailgun",
"mailgun_domain": "المجال",
"mailgun_endpoint": "النهاية الطرفية لـ Mailgun",
"ses_secret": "SES الرمز السري",
"ses_key": "SES مفتاح",
"password": "كلمة مرور البريد الالكتروني",
"username": "اسم المستخدم للبريد الإلكتروني",
"mail_config": "إعدادات البريد الالكتروني",
"from_name": "اسم المرسل",
"from_mail": "عنوان البريد الالكتروني للمرسل",
"encryption": "صيغة ا لتشفير",
"mail_config_desc": "أدناه هو نموذج لتكوين برنامج تشغيل البريد الإلكتروني لإرسال رسائل البريد الإلكتروني من التطبيق. يمكنك أيضًا تهيئة موفري الجهات الخارجية مثل Sendgrid و SES إلخ."
},
"pdf": {
"title": "PDF إعدادات",
"footer_text": "نص التذييل",
"pdf_layout": "اتجاه صفحة PDF"
},
"company_info": {
"company_info": "معلومات الشركة",
"company_name": "اسم الشركة",
"company_logo": "شعار الشركة",
"section_description": "معلومات عن شركتك سيتم عرضها على الفواتير والتقديرات والمستندات الأخرى.",
"phone": "الهاتف",
"country": "الدولة",
"state": "الولاية/المنطقة",
"city": "المدينة",
"address": "العنوان",
"zip": "الرمز البريدي",
"save": "حفظ",
"updated_message": "تم تحديث معلومات الشركة بنجاح"
},
"customization": {
"customization": "التخصيص",
"save": "حفظ",
"addresses": {
"title": "العنوان",
"section_description": "يمكنك ضبط عنوان إرسال فواتير العملاء وتنسيق عنوان شحن العملاء (معروض في PDF فقط).",
"customer_billing_address": "عنوان فواتير العميل",
"customer_shipping_address": "عنوان الشحن للعميل",
"company_address": "عنوان الشركة",
"insert_fields": "أضف حقل",
"contact": "تواصل",
"address": "العنوان",
"display_name": "الاسم الظاهر",
"primary_contact_name": "مسؤول التواصل الرئيسي",
"email": "البريد الإلكتروني",
"website": "موقع الإنترنت",
"name": "الاسم",
"country": "الدولة",
"state": "الولاية/المنطقة",
"city": "المدينة",
"company_name": "اسم الشركة",
"address_street_1": "عنوان الشارع 1",
"address_street_2": "عنوان الشارع 2",
"phone": "الهاتف",
"zip_code": "الرمز البريدي",
"address_setting_updated": "تم تحديث العنوان بنجاح"
},
"updated_message": "تم تحديث معلومات الشركة بنجاح",
"invoices": {
"title": "الفواتير",
"notes": "ملاحظات",
"invoice_prefix": "بادئة رقم الفاتورة",
"invoice_settings": "إعدادات الفاتورة",
"autogenerate_invoice_number": "ترقيم آلي للفاتورة",
"invoice_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الفاتورة تلقائيًا في كل مرة تقوم فيها بإنشاء فاتورة جديدة.",
"enter_invoice_prefix": "أدخل بادئة رقم الفاتورة",
"terms_and_conditions": "الأحكام والشروط",
"invoice_setting_updated": "تم تحديث إعداد الفاتورة بنجاح"
},
"estimates": {
"title": "التقديرات",
"estimate_prefix": "بادئة رقم التقدير",
"estimate_settings": "إعدادت التقدير",
"autogenerate_estimate_number": "ترقيم آلي للتقدير",
"estimate_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام التقديرات تلقائيًا في كل مرة تقوم فيها بإنشاء تقدير جديد.",
"enter_estimate_prefix": "أدخل بادئة رقم التقدير",
"estimate_setting_updated": "تم تحديث إعدادات التقدير بنجاح"
},
"payments": {
"title": "المدفوعات",
"payment_prefix": "بادئة رقم الدفعة",
"payment_settings": "إعدادات الدفعة",
"autogenerate_payment_number": "ترقيم آلي للمدفوعات",
"payment_setting_description": "تعطيل الترقيم الآلي ، إذا كنت لا ترغب في إنشاء أرقام الدفعة تلقائيًا في كل مرة تقوم فيها بإنشاء دفعة جديدة.",
"enter_payment_prefix": "أدخل بادئة رقم الدفعة",
"payment_setting_updated": "تم تحديث إعدادات الدفعة بنجاح"
}
},
"account_settings": {
"profile_picture": "صورة الملف الشخصي",
"name": "الاسم",
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"confirm_password": "أعد كتابة كلمة المرور",
"account_settings": "إعدادات الجساب",
"save": "حفظ",
"section_description": "يمكنك تحديث اسمك والبريد الإلكتروني وكلمة المرور باستخدام النموذج أدناه.",
"updated_message": "تم تحديث إعدادات الحساب بنجاح"
},
"user_profile": {
"name": "الاسم",
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"confirm_password": "أعد كتابة كلمة المرور"
},
"notification": {
"title": "الإشعارات",
"email": "إرسال الإشعارات إلى",
"description": "ما هي إشعارات البريد الإلكتروني التي ترغب في تلقيها عندما يتغير شيء ما؟",
"invoice_viewed": "تم عرض الفاتورة",
"invoice_viewed_desc": "عندما يستعرض عميلك الفاتورة المرسلة عبر الشاشة الرئيسية.",
"estimate_viewed": "تم عرض التقدير",
"estimate_viewed_desc": "عندما يستعرض عميلك التقدير المرسلة عبر الشاشة الرئيسية.",
"save": "حفظ",
"email_save_message": "تم حفظ البريد الإلكتروني بنجاح",
"please_enter_email": "فضلاً أدخل البريد الإلكتروني"
},
"tax_types": {
"title": "أنواع الضرائب",
"add_tax": "أضف ضريبة",
"description": "يمكنك إضافة أو إزالة الضرائب كما يحلو لك. النظام يدعم الضرائب على العناصر الفردية وكذلك على الفاتورة.",
"add_new_tax": "إضافة ضريبة جديدة",
"tax_settings": "إعدادات الضريبة",
"tax_per_item": "ضريبة على الصنف",
"tax_name": "اسم الضريبة",
"compound_tax": "ضريبة مجمعة",
"percent": "نسبة مؤوية",
"action": "إجراء",
"tax_setting_description": "قم بتمكين هذا إذا كنت تريد إضافة ضرائب لعناصر الفاتورة الفردية. بشكل افتراضي ، تضاف الضرائب مباشرة إلى الفاتورة.",
"created_message": "تم إنشاء نوع الضريبة بنجاح",
"updated_message": "تم تحديث نوع الضريبة بنجاح",
"deleted_message": "تم حذف نوع الضريبة بنجاح",
"confirm_delete": "لن تتمكن من استرجاع نوع الضرية هذا",
"already_in_use": "ضريبة قيد الاستخدام"
},
"expense_category": {
"title": "فئات النفقات",
"action": "إجراء",
"description": "الفئات مطلوبة لإضافة إدخالات النفقات. يمكنك إضافة أو إزالة هذه الفئات وفقًا لتفضيلاتك.",
"add_new_category": "إضافة فئة جديدة",
"category_name": "اسم الفئة",
"category_description": "الوصف",
"created_message": "تم إنشاء نوع النفقات بنجاح",
"deleted_message": "تم حذف نوع النفقات بنجاح",
"updated_message": "تم تحديث نوع النفقات بنجاح",
"confirm_delete": "لن تتمكن من استرجاع نوع النفقات هذا",
"already_in_use": "نوع قيد الاستخدام"
},
"preferences": {
"currency": "العملة",
"language": "اللغة",
"time_zone": "المنطة الزمنية",
"fiscal_year": "السنة المالية",
"date_format": "صيغة التاريخ",
"discount_setting": "إعدادات الخصم",
"discount_per_item": "خصم على الصنف ",
"discount_setting_description": "قم بتمكين هذا إذا كنت تريد إضافة خصم إلى عناصر الفاتورة الفردية. بشكل افتراضي ، يتم إضافة الخصم مباشرة إلى الفاتورة.",
"save": "حفظ",
"preference": "تفضيل | تفضيلات",
"general_settings": "التفضيلات الافتراضية للنظام.",
"updated_message": "تم تحديث التفضيلات بنجاح",
"select_language": "اختر اللغة",
"select_time_zone": "اختر المنطة الزمنية",
"select_date_formate": "اختر صيغة التاريخ",
"select_financial_year": "اختر السنة المالية"
},
"update_app": {
"title": "تحديث النظام",
"description": "يمكنك تحديث النظام بسهولة عن طريق البحث عن تحديث جديد بالنقر فوق الزر أدناه",
"check_update": "تحقق من التحديثات",
"avail_update": "تحديث جديد متوفر",
"next_version": "النسخة الجديدة",
"update": "حدث الآن",
"update_progress": "قيد التحديث...",
"progress_text": "سوف يستغرق التحديث بضع دقائق. يرجى عدم تحديث الشاشة أو إغلاق النافذة قبل انتهاء التحديث",
"update_success": "تم تحديث النظام! يرجى الانتظار حتى يتم إعادة تحميل نافذة المتصفح تلقائيًا.",
"latest_message": "لا يوجد تحديثات متوفرة! لديك حالياً أحدث نسخة.",
"current_version": "النسخة الحالية"
}
},
"wizard": {
"account_info": "معلومات الحساب",
"account_info_desc": "سيتم استخدام التفاصيل أدناه لإنشاء حساب المسؤول الرئيسي. كما يمكنك تغيير التفاصيل في أي وقت بعد تسجيل الدخول.",
"name": "الاسم",
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"confirm_password": "أعد كتابة كلمة المرور",
"save_cont": "حفظ واستمرار",
"company_info": "معلومات الشركة",
"company_info_desc": "سيتم عرض هذه المعلومات على الفواتير. لاحظ أنه يمكنك تعديل هذا لاحقًا في صفحة الإعدادات.",
"company_name": "اسم الشركة",
"company_logo": "شعار الشركة",
"logo_preview": "استعراض الشعار",
"preferences": "التفضيلات",
"preferences_desc": "التفضيلات الافتراضية للنظام",
"country": "الدولة",
"state": "الولاية/المنطقة",
"city": "المدينة",
"address": "العنوان",
"street": "العنوان 1 | العنوان 2",
"phone": "الهاتف",
"zip_code": "الرمز البريدي",
"go_back": "للخلف",
"currency": "العملة",
"language": "اللغة",
"time_zone": "المنطة الزمنية",
"fiscal_year": "السنة المالية",
"date_format": "صيغة التاريخ",
"from_address": "من العنوان",
"username": "اسم المستخدم",
"next": "التالي",
"continue": "استمرار",
"skip": "تخطي",
"database": {
"database": "عنوان قاعدة البيانات",
"connection": "اتصال قاعدة البيانات",
"host": "خادم قاعدة البيانات",
"port": "منفذ قاعدة البيانات",
"password": "كلمة مرور قاعدة البيانات",
"app_url": "عنوان الإنترنت للنظام",
"username": "اسم المستخدم لقاعدة البيانات",
"db_name": "سم قاعدة البيانات",
"desc": "قم بإنشاء قاعدة بيانات على الخادم الخاص بك وتعيين بيانات الاعتماد باستخدام النموذج أدناه."
},
"permissions": {
"permissions": "الأذونات",
"permission_confirm_title": "هل أنت متأكد من الاستمرار؟",
"permission_confirm_desc": "فشل فحص أذونات المجلد",
"permission_desc": "فيما يلي قائمة أذونات المجلد المطلوبة حتى يعمل التطبيق. في حالة فشل فحص الإذن ، تأكد من تحديث أذونات المجلد."
},
"mail": {
"host": "خادم البريد",
"port": "منفذ البريد",
"driver": "مشغل البريد",
"secret": "سري",
"mailgun_secret": "الرمز السري لـ Mailgun",
"mailgun_domain": "المجال",
"mailgun_endpoint": "النهاية الطرفية لـ Mailgun",
"ses_secret": "SES الرمز السري",
"ses_key": "SES مفتاح",
"password": "كلمة مرور البريد الالكتروني",
"username": "اسم المستخدم للبريد الإلكتروني",
"mail_config": "إعدادات البريد الالكتروني",
"from_name": "اسم المرسل",
"from_mail": "عنوان البريد الالكتروني للمرسل",
"encryption": "صيغة ا لتشفير",
"mail_config_desc": "أدناه هو نموذج لتكوين برنامج تشغيل البريد الإلكتروني لإرسال رسائل البريد الإلكتروني من التطبيق. يمكنك أيضًا تهيئة موفري الجهات الخارجية مثل Sendgrid و SES إلخ."
},
"req": {
"system_req": "متطلبات النظام",
"php_req_version": "Php (النسخة المطلوبة {version} بحد أدنى)",
"check_req": "فحص متطلبات النظام",
"system_req_desc": "يحتوي النظام على بعض متطلبات الخادم. تأكد من أن خادمك لديه نسخة php المطلوبة وجميع الامتدادات المذكورة أدناه."
},
"errors": {
"migrate_failed": "فشل إنشاء الجداول",
"database_variables_save_error": "غير قادر على الاتصال بقاعدة البيانات باستخدام القيم المقدمة.",
"mail_variables_save_error": "فشل تكوين البريد الإلكتروني.",
"connection_failed": "فشل اتصال قاعدة البيانات",
"database_should_be_empty": "يجب أن تكون قاعدة البيانات فارغة"
},
"success": {
"mail_variables_save_successfully": "تم تكوين البريد الإلكتروني بنجاح",
"database_variables_save_successfully": "تم تكوين قاعدة البيانات بنجاح."
}
},
"layout_login": {
"copyright_crater": "حقوق الطبع والنشر @ كريتر - 2020",
"super_simple_invoicing": "فوترة سهلة ومبسطة للغاية",
"for_freelancer": "للمبرمجين المستقلين",
"small_businesses": "والأعال الصغيرة ",
"crater_help": "كريتر يساعدك على تتبع النفقات وتسجيل المدفوعات وإنشاء",
"invoices_and_estimates": "الفواتير والتقديرات مع إمكانية اختيار قوالب متعددة."
},
"validation": {
"invalid_url": "عنوان انترنت غير صحيح (مثال: http://www.crater.com)",
"required": "حقل مطلوب",
"email_incorrect": "بريد الكتروني غير صحيح.",
"email_already_taken": "هذا البريد الالكتروني مستخدم مسبقاً",
"email_does_not_exist": "لا يوجد كستخدم بهذا البريد الالكتروني",
"item_unit_already_taken": "وحدة البند قد اتخذت بالفعل",
"payment_mode_already_taken": "لقد تم بالفعل أخذ طريقة الدفع",
"send_reset_link": "أرسال رابط استعادة كلمة المرور",
"not_yet": "ليس بعد؟ أعد الإرسال الآن..",
"password_min_length": "كلمة المرور يجب أن تتكون من {count} أحرف على الأقل",
"name_min_length": "الاسم يجب أن يتكون من {count} أحرف على الأقل",
"enter_valid_tax_rate": "أدخل معدل الضريبة بشكل صحيح",
"numbers_only": "أرقام فقط.",
"characters_only": "حروف فقط.",
"password_incorrect": "يجب أن تكون كلمات المرور متطابقة",
"password_length": "يجب أن تكون كلمة المرور بطول {count} حرف.",
"qty_must_greater_than_zero": "الكمية يجب أن تكون أكبر من صفر.",
"price_greater_than_zero": "السعر يجب أن يكون أكبر من صفر.",
"payment_greater_than_zero": "الدفعة يجب أن تكون أكبر من صفر.",
"payment_greater_than_due_amount": "مبلغ الدفعة أكثر من المبلغ المستحق لهذه الفاتورة.",
"quantity_maxlength": "يجب ألا تزيد الكمية عن 20 رقماً.",
"price_maxlength": "يجب ألا يزيد السعر عن 20 رقماً.",
"price_minvalue": "يجب أن يكون السعر أكبر من صفر.",
"amount_maxlength": "يجب ألا يزيد المبلغ عن 20 رقماً.",
"amount_minvalue": "يجب أن يكون المبلغ أكبر من صفر.",
"description_maxlength": "يجب ألا يزيد الوصف عن 255 حرفاً.",
"maximum_options_error": "الحد الأعلى هو {max} خيارات. قم بإزالة أحد الخيارات لتحديد خيار آخر.",
"notes_maxlength": "يجب ألا يزيد حجم الملاحظات عن 255 حرفاً.",
"address_maxlength": "يجب ألا يزيد العنوان عن 255 حرفاً.",
"ref_number_maxlength": "يجب ألا يزيد الرقم المرجعي عن 255 حرفاً.",
"prefix_maxlength": "يجب ألا تزيد البادئة عن 5 أحرف."
}
}

View File

@ -0,0 +1,878 @@
{
"credit_notes": {
"action": "Aktion",
"amount": "Summe",
"confirm_delete": "Wollen Sie diese Gutschrift löschen?",
"contact": "Kontakt",
"credit_notes": "Gutschriften",
"credit_notes_list": "Gutschriften-Liste",
"credit_number": "Kreditkarten-Nummer",
"date": "Datum",
"item": {
"description": "Beschreibung",
"discount": "Rabatt",
"price": "Preis",
"quantity": "Menge",
"sub_total": "Zwischensumme",
"tax": "Steuer",
"title": "Titel",
"total": "Gesamt",
"total_discount": "Rabatt Gesamt"
},
"notes": "Hinweise",
"title": "Gutschriften"
},
"customers": {
"action": "Aktion",
"add_customer": "Kunde hinzufügen",
"add_new_customer": "Neuen Kunden hinzufügen",
"added_on": "Hinzugefügt am",
"address": "Adresse",
"amount_due": "Offener Betrag",
"basic_info": "Basisinformation",
"billing_address": "Rechnungsadresse",
"city": "Stadt",
"confirm_delete": "Sie können diesen Kunden nicht wiederherstellen | Sie können diese Kunden nicht wiederherstellen",
"contact_name": "Kontakt Name",
"contacts_list": "Kunden-Liste",
"copy_billing_address": "Rechnungsadresse kopieren",
"country": "Land",
"created_message": "Kunde erfolgreich erstellt",
"customer": "Kunde | Kunden",
"deleted_message": "Kunden erfolgreich gelöscht | Kunden erfolgreich gelöscht",
"display_name": "Anzeige Name",
"edit_customer": "Kunde bearbeiten",
"email": "E-Mail",
"list_of_customers": "Dieser Abschnitt enthält die Liste der Kunden.",
"name": "Name",
"new_customer": "Neuer Kunde",
"no_customers": "Noch keine Kunden!",
"no_customers_found": "Keine Kunden gefunden!",
"password": "Passwort",
"phone": "Telefon",
"primary_contact_name": "Ansprechpartner",
"primary_currency": "Primäre Währung",
"primary_display_name": "Primärer Anzeige Name",
"save_customer": "Kunde speichern",
"select_a_customer": "Wählen Sie einen Kunden",
"select_city": "Stadt wählen",
"select_country": "Land wählen",
"select_currency": "Währung wählen",
"select_state": "Bundesland wählen",
"shipping_address": "Versand-Adresse",
"state": "Bundesland",
"street_1": "Strasse",
"street_2": "Adresszusatz",
"street_number": "Hausnummer",
"title": "Kunden",
"type_or_click": "Eingeben oder anklicken zum auswählen",
"update_customer": "Kunden ändern",
"updated_message": "Kunde erfolgreich aktualisiert",
"website": "Webseite",
"zip_code": "PLZ"
},
"dashboard": {
"cards": {
"customers": "Kunden",
"due_amount": "Offene Beträge",
"estimates": "Kostenvoranschläge",
"invoices": "Rechnungen"
},
"chart_info": {
"net_income": "Einnahmen Netto",
"total_expense": "Gesamtausgaben",
"total_receipts": "Eingänge gesamt",
"total_sales": "Verkäufe gesamt",
"year": "Jahr"
},
"monthly_chart": {
"title": "Umsatz & Kosten"
},
"recent_estimate_card": {
"actions": "Aktionen",
"amount_due": "Betrag",
"customer": "Kunden",
"date": "Datum",
"title": "Aktuelle Kostenvoranschläge",
"view_all": "Alle Anzeigen"
},
"recent_invoices_card": {
"actions": "Aktionen",
"amount_due": "Offener Betrag",
"customer": "Kunden",
"due_on": "Fällig am",
"title": "Fällige Rechnungen",
"view_all": "Alle Anzeigen"
},
"select_year": "Jahr wählen",
"weekly_invoices": {
"title": "Wöchentliche Rechnungen"
}
},
"estimates": {
"Estimate": "Kostenvoranschlag | Kostenvoranschläge",
"accepted": "Angenommen",
"action": "Aktion",
"add_estimate": "Kostenvoranschlag hinzufügen",
"add_item": "Fügen Sie ein Artikel hinzu",
"add_new_estimate": "Neuen Kostenvoranschlag hinzufügen",
"add_new_tax": "neuen Steuersatz hinzufügen",
"add_tax": "Steuer hinzufügen",
"all": "Alle",
"amount": "Summe",
"amount_due": "OFFENER BETRAG",
"confirm_conversion": "Sie möchten, konvertieren Sie diese Schätzung in die Rechnung?",
"confirm_delete": "Der Kostenvoranschlag kann nicht wiederhergestellt werden | Die Kostenvoranschläge können nicht wiederhergestellt werden",
"confirm_mark_as_accepted": "Dieser Kostenvoranschlag wird als angenommen markiert",
"confirm_mark_as_rejected": "Dieser Kostenvoranschlag wird als abgelehnt markiert",
"confirm_mark_as_sent": "Dieser Kostenvoranschlag wird als gesendet markiert",
"confirm_send_estimate": "Der Kostenvoranschlag wird per E-Mail an den Kunden gesendet",
"contact": "Kontakt",
"conversion_message": "Rechnung erfolgreich erstellt",
"convert_to_invoice": "Konvertieren in Rechnung",
"created_message": "Kostenvoranschlag erfolgreich erstellt",
"customer": "KUNDEN",
"date": "Datum",
"days": "{days} Tage",
"declined": "Abgelehnt",
"deleted_message": "Kostenvoranschlag erfolgreich gelöscht | Kostenvoranschläge erfolgreich gelöscht",
"discount": "Rabatt",
"draft": "Entwurf",
"due_date": "Fälligkeit",
"edit_estimate": "Kostenvoranschlag ändern",
"errors": {
"required": "Feld ist erforderlich"
},
"estimate": "Kostenvoranschlag | Kostenvoranschläge",
"estimate_number": "Kostenvoran. Nummer",
"estimate_template": "Vorlage",
"estimates_list": "Liste Kostenvoranschläge",
"expiry_date": "Zahlungsziel",
"item": {
"amount": "Summe",
"description": "Beschreibung",
"discount": "Rabatt",
"price": "Preis",
"quantity": "Menge",
"select_an_item": "Wählen Sie einen Artikel",
"sub_total": "Zwischensumme",
"tax": "Steuer",
"title": "Titel",
"total": "Gesamt",
"total_discount": "Rabatt Gesamt",
"type_item_description": "Artikel Beschreibung (optional)"
},
"items": "Artikel",
"list_of_estimates": "Dieser Abschnitt enthält die Liste der Kostenvoranschläge.",
"mark_as_accepted": "Markiert als angenommen",
"mark_as_rejected": "Markiert als abgelehnt",
"mark_as_sent": "Als gesendet markieren",
"mark_as_sent_successfully": "Kostenvoranschlag als gesendet markiert.",
"marked_as_accepted_message": "Kostenvoranschlag als angenommen markiert",
"marked_as_rejected_message": "Kostenvoranschlag als abgelehnt markiert",
"months": "{months} Monat",
"new_estimate": "Neuer Kostenvoranschlag",
"no_estimates": "Keine Kostenvoranschläge vorhanden!",
"no_matching_estimates": "Es gibt keine übereinstimmenden Kostenvoranschläge!",
"notes": "Hinweise",
"number": "ANZAHL",
"paid": "Bezahlt",
"partially_paid": "Teilweise bezahlt",
"record_payment": "Zahlung erfassen",
"ref_no": "REF. - NR.",
"ref_number": "Ref-Nummer",
"save_estimate": "Kostenvoranschlag speichern",
"send_estimate": "Kostenvoranschlag senden",
"send_estimate_successfully": "Kostenvoranschlag erfolgreich gesendet",
"sent": "Gesendet",
"something_went_wrong": "Da ging etwas schief",
"status": "Status",
"sub_total": "Zwischensumme",
"tax": "Steuer",
"title": "Kostenvoranschläge",
"total": "Gesamt",
"unpaid": "Unbezahlte",
"update_Estimate": "Kostenvoranschlag aktualisieren",
"updated_message": "Kostenvoranschlag erfolgreich aktualisiert",
"user_email_does_not_exist": "Benutzer-E-Mail nicht vorhanden",
"years": "{years} Jahre"
},
"expenses": {
"action": "Aktion",
"add_expense": "Aufwendung hinzufügen",
"add_new_expense": "Neue Aufwendung hinzufügen",
"amount": "Summe",
"categories": {
"actions": "Aktionen",
"add_category": "Kategorie hinzufügen",
"amount": "Summe",
"categories_list": "Liste der Kategorien",
"category": "Kategorie | Kategorien",
"description": "Beschreibung",
"name": "Name",
"new_category": "Neue Kategorie",
"select_a_category": "Wählen Sie eine Kategorie",
"title": "Titel"
},
"category": "Kategorie",
"category_id": "Kategorie-Id",
"confirm_delete": "Sie können diese Ausgabe nicht wiederherstellen. | Sie können diese Ausgaben nicht wiederherstellen.",
"contact": "Kontakt",
"created_message": "Aufwand erfolgreich erstellt",
"date": "Aufwandsdatum",
"deleted_message": "Aufwand erfolgreich gelöscht | Aufwand erfolgreich gelöscht",
"description": "Beschreibung",
"download_receipt": "Quittung herunterladen",
"edit_expense": "Aufwendung ändern",
"expense": "Aufwendung | Aufwendungen",
"expense_date": "Datum",
"expense_title": "Titel",
"expenses_list": "Liste der Ausgaben",
"from_date": "Von Datum",
"list_of_expenses": "Dieser Abschnitt enthält die Liste der Ausgaben.",
"new_expense": "Neue Aufwendung",
"no_expenses": "Noch keine Ausgaben!",
"note": "Hinweis",
"receipt": "Eingang",
"save_expense": "Aufwendung speichern",
"title": "Aufwendungen/Ausgaben",
"to_date": "bis Datum",
"update_expense": "Aufwendung aktualisieren",
"updated_message": "Aufwand erfolgreich aktualisiert"
},
"general": {
"action_failed": "Aktion fehlgeschlagen",
"actions": "Aktionen",
"add_new_item": "Artikel hinzufügen",
"all": "Alle",
"are_you_sure": "Sind Sie sicher?",
"back_to_login": "Zurück zum Login?",
"bill_to": "Rechnungsempfänger",
"bytefury": "Bytefury",
"cancel": "Abrechen",
"choose": "Wählen",
"choose_file": "Klicken Sie hier, um eine Datei auszuwählen",
"choose_template": "Wählen Sie eine Vorlage",
"clear_all": "Alle entfernen",
"delete": "Löschen",
"discount": "RABATT",
"download": "Download",
"download_pdf": "Download PDF",
"draft": "Entwurf",
"due": "Fällig",
"edit": "Ändern",
"filter": "Filter",
"fixed": "Behoben",
"four_zero_four": "Vier hundert vier",
"from": "Von",
"from_date": "Von Datum",
"go_back": "zurück",
"go_home": "Geh zurück",
"home": "Startseite",
"list_is_empty": "Liste ist leer.",
"no_tax_found": "Kein Steuersatz gefunden!",
"of": "von",
"percentage": "Prozentsatz",
"powered_by": "Powered by",
"remove": "Entfernen",
"save": "Speichern",
"search": "Suchen",
"select_a_status": "Status wählen",
"select_a_tax": "Steuersatz wählen",
"select_all": "Alle auswählen",
"select_city": "Stadt wählen",
"select_country": "Land wählen",
"select_state": "Bundesland wählen",
"sent": "Gesendet",
"setting_updated": "Einstellungen erfolgreich aktualisiert",
"ship_to": "Versand ein",
"showing": "Anzeigen",
"street_1": "Straße",
"street_2": "Zusatz Strasse",
"subtotal": "ZWISCHENSUMME",
"tax": "Steuer",
"to": "bis",
"to_date": "bis Datum",
"total_amount": "GESAMTSUMME",
"update": "Update",
"view": "Anzeigen",
"view_pdf": "PDF anzeigen",
"you_got_lost": "Hoppla! Du hast dich verirrt!"
},
"invoices": {
"action": "Aktion",
"add_item": "Fügen Sie ein Artikel hinzu",
"add_new_invoice": "Neue Rechnung hinzufügen",
"add_new_tax": "Neuen Steuersatz hinzufügen",
"add_tax": "Steuersatz hinzufügen",
"all": "Alle",
"amount": "Summe",
"amount_due": "OFFENER BETRAG",
"confirm_delete": "Sie können diese Rechnung nicht wiederherstellen. | Sie können diese Rechnungen nicht wiederherstellen.",
"confirm_send": "Diese Rechnung wird per E-Mail an den Kunden gesendet",
"confirm_send_invoice": "Diese Rechnung wird per E-Mail an den Kunden gesendet",
"contact": "Kontakt",
"created_message": "Rechnung erfolgreich erstellt",
"customer": "KUNDEN",
"date": "Datum",
"days": "{days} Tage",
"deleted_message": "Rechnung erfolgreich gelöscht | Rechnungen erfolgreich gelöscht",
"discount": "Rabatt",
"due_date": "Fälligkeit",
"edit_invoice": "Rechnung bearbeiten",
"invalid_due_amount_message": "Der Gesamtrechnungsbetrag darf nicht kleiner sein als der für diese Rechnung bezahlte Gesamtbetrag. Bitte aktualisieren Sie die Rechnung oder löschen Sie die zugehörigen Zahlungen um fortzufahren.",
"invoice": "Rechnung | Rechnungen",
"invoice_date": "Rechnungsdatum",
"invoice_mark_as_sent": "Diese Rechnung wird als gesendet markiert",
"invoice_number": "Rechnungsnummer",
"invoice_template": "Rechnungs-Vorlage",
"invoices_list": "Liste der Rechnungen",
"item": {
"amount": "Summe",
"description": "Beschreibung",
"discount": "Rabatt",
"price": "Preis",
"quantity": "Menge",
"select_an_item": "Geben Sie oder wählen Sie ein Artikel",
"sub_total": "Zwischensumme",
"tax": "Steuer",
"title": "Titel",
"total": "Gesamt",
"total_discount": "Rabatt Gesamt",
"type_item_description": "Artikel Beschreibung (optional)"
},
"list_of_invoices": "Dieser Abschnitt enthält die Liste der Rechnungen.",
"mark_as_sent": "Als gesendet markieren",
"mark_as_sent_successfully": "Rechnung gekennzeichnet als erfolgreich gesendet",
"marked_as_sent_message": "Rechnung als erfolgreich gesendet markiert",
"months": "{months} Monat",
"new_invoice": "Neue Rechnung",
"no_invoices": "Keine Rechnungen vorhanden!",
"no_matching_invoices": "Es gibt keine entsprechenden Rechnungen!",
"notes": "Hinweise",
"number": "ANZAHL",
"paid": "Bezahlt",
"paid_status": "BEZAHLT-STATUS",
"partially_paid": "Teilzahlung",
"payment_attached_message": "Einer der ausgewählten Rechnungen ist bereits eine Zahlung zugeordnet. Stellen Sie sicher, dass Sie zuerst die angehängten Zahlungen löschen, um mit dem Entfernen fortzufahren",
"record_payment": "Zahlung erfassen",
"ref_no": "REF. - NR.",
"ref_number": "Ref-Nummer",
"save_invoice": "Rechnung speichern",
"select_invoice": "Wählen Sie eine Rechnung",
"send_invoice": "Rechnung senden",
"send_invoice_successfully": "Rechnung erfolgreich versendet",
"something_went_wrong": "Da ist etwas schief gelaufen",
"status": "Status",
"sub_total": "Zwischensumme",
"template": "Vorlage",
"title": "Rechnungen",
"total": "Gesamt",
"unpaid": "Unbezahlte",
"update_expense": "Kosten aktualisieren",
"update_invoice": "Rechnung ändern",
"updated_message": "Rechnung erfolgreich aktualisiert",
"user_email_does_not_exist": "Benutzer-E-Mail existiert nicht",
"view": "Anzeigen",
"years": "{years} Jahre"
},
"items": {
"action": "Aktion",
"add_item": "Artikel hinzufügen",
"add_new_item": "Neuen Artikel hinzufügen",
"added_on": "Hinzugefügt am",
"confirm_delete": "Sie können diesen Artikel nicht wiederherstellen | Sie können diese Artikel nicht wiederherstellen",
"created_message": "Artikel erfolgreich erstellt",
"date_of_creation": "Erstellt am",
"deleted_message": "Artikel erfolgreich gelöscht | Artikel erfolgreich gelöscht",
"description": "Beschreibung",
"edit_item": "Artikel bearbeiten",
"item": "Artikel | Artikel",
"item_attached_message": "Ein Artikel der bereits verwendet wird kann nicht gelöscht werden",
"items_list": "Artikel-Liste",
"list_of_items": "Dieser Abschnitt enthält die Liste der Artikel.",
"name": "Name",
"new_item": "Neuer Artikel",
"no_items": "Keine Artikel vorhanden!",
"price": "Preis",
"save_item": "Artikel speichern",
"select_a_unit": "wählen Sie die Einheit",
"title": "Artikel",
"unit": "Einheit",
"update_item": "Artikel ändern",
"updated_message": "Artikel erfolgreich aktualisiert"
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2019",
"crater_help": "Crater helps you track expenses, record payments & generate beautiful",
"for_freelancer": "for Freelancers &",
"invoices_and_estimates": "invoices & estimates with ability to choose multiple templates.",
"small_businesses": "Small Businesses ",
"super_simple_invoicing": "Super Simple Invoicing"
},
"login": {
"email": "E-Mail",
"enter_email": "Geben Sie Ihre E-Mail ein",
"enter_password": "Geben Sie das Passwort ein",
"forgot_password": "Passwort vergessen?",
"login": "Anmelden",
"login_placeholder": "mail@example.com",
"or_signIn_with": "oder Anmelden mit",
"password": "Passwort",
"password_reset_successfully": "Passwort erfolgreich zurückgesetzt",
"register": "Registrieren",
"reset_password": "Passwort zurücksetzen",
"retype_password": "Passwort bestätigen"
},
"navigation": {
"customers": "Kunden",
"dashboard": "Übersicht",
"estimates": "Kostenvoranschläge",
"expenses": "Kosten",
"invoices": "Rechnungen",
"items": "Artikel",
"logout": "Abmelden",
"payments": "Zahlungen",
"reports": "Berichte",
"settings": "Einstellungen"
},
"payments": {
"action": "Aktion",
"add_new_payment": "Neue Zahlung hinzufügen",
"add_payment": "Zahlung hinzufügen",
"amount": "Summe",
"confirm_delete": "Sie können diese Zahlung nicht wiederherstellen. | Sie können diese Zahlungen nicht wiederherstellen.",
"created_message": "Zahlung erfolgreich erstellt",
"customer": "Kunden",
"date": "Datum",
"deleted_message": "Zahlung erfolgreich gelöscht | Zahlungen erfolgreich gelöscht",
"edit_payment": "Zahlung bearbeiten",
"invalid_amount_message": "Zahlungsbetrag ist ungültig",
"invoice": "Rechnung",
"list_of_payments": "Dieser Abschnitt enthält die Liste der Zahlungen.",
"new_payment": "Neue Zahlung",
"no_payments": "Keine Zahlungen vorhanden!",
"no_matching_payments": "Es gibt keine passenden Zahlungen!",
"note": "Hinweis",
"payment": "Zahlung | Zahlungen",
"payment_mode": "Zahlungsart",
"payment_number": "Zahlungsnummer",
"payments_list": "Liste der Zahlungen",
"record_payment": "Zahlung eintragen",
"save_payment": "Zahlung speichern",
"select_payment_mode": "Wählen Sie den Zahlungsmodus",
"title": "Zahlungen",
"update_payment": "Zahlung ändern",
"updated_message": "Zahlung erfolgreich aktualisiert",
"view_payment": "Zahlung anzeigen"
},
"reports": {
"download_pdf": "Download PDF",
"errors": {
"required": "Feld ist erforderlich"
},
"estimates": {
"amount": "Summe",
"contact_name": "Ansprechpartner",
"due_date": "Fälligkeit",
"estimate": "Kostenvoranschlag",
"estimate_date": "Datum Kostenvoranschlag",
"estimate_number": "Kostenvoranschlag-Nr.",
"ref_number": "Ref-Nummer",
"status": "Status"
},
"expenses": {
"amount": "Summe",
"category": "Kategorie",
"date": "Datum",
"date_range": "Datumsbereich auswählen",
"expenses": "Aufwendungen",
"from_date": "Ab Datum",
"to_date": "bis Datum"
},
"from_date": "Ab Datum",
"invoices": {
"amount": "Summe",
"contact_name": "Ansprechpartner",
"due_date": "Fälligkeit",
"invoice": "Rechnung",
"invoice_date": "Rechnungsdatum",
"status": "Status"
},
"paid": "Bezahlt",
"profit_loss": {
"date_range": "Datumsbereich auswählen",
"from_date": "Ab Datum",
"profit_loss": "Gewinn & Verlust",
"to_date": "bis Datum"
},
"report": "Bericht | Berichte",
"sales": {
"date_range": "Datumsbereich auswählen",
"from_date": "Ab Datum",
"report_type": "Berichtstyp",
"sales": "Vertrieb",
"to_date": "bis Datum"
},
"status": "Status",
"taxes": {
"date_range": "Datumsbereich auswählen",
"from_date": "Ab Datum",
"taxes": "Steuern",
"to_date": "bis Datum"
},
"title": "Bericht",
"to_date": "bis Datum",
"unpaid": "Unbezahlt",
"update_report": "Bericht aktualisieren",
"view_pdf": "PDF anzeigen"
},
"settings": {
"account_settings": {
"account_settings": "Konto-Einstellungen",
"confirm_password": "Kennwort Bestätigen",
"email": "E-Mail",
"name": "Name",
"password": "Passwort",
"profile_picture": "Profil Bild",
"save": "Speichern",
"section_description": "Sie können Ihren Namen, Ihre E-Mail-Adresse und Ihr Passwort mit dem folgenden Formular aktualisieren.",
"updated_message": "Kontoeinstellungen erfolgreich aktualisiert"
},
"company_info": {
"address": "Adresse",
"city": "Stadt",
"company_info": "Firmeninfo",
"company_logo": "Firmenlogo",
"company_name": "Name des Unternehmens",
"country": "Land",
"phone": "Telefon",
"save": "Speichern",
"section_description": "Informationen zu Ihrem Unternehmen, die auf Rechnungen, Kostenvoranschlägen und anderen von Crater erstellten Dokumenten angezeigt werden.",
"state": "Bundesland",
"updated_message": "Unternehmensinformationen wurden erfolgreich aktualisiert",
"zip": "PLZ"
},
"currencies": {
"action": "Aktion",
"add_currency": "Währung einfügen",
"code": "Code",
"currencies_list": "Währungen Liste",
"currency": "Währung | Währungen",
"decimal_separator": "Decimal-Separator",
"left": "Links",
"name": "Name",
"position": "Position",
"position_of_symbol": "Position des Währungssymbol",
"precision": "Präzision",
"right": "Rechts",
"select_currency": "Währung wählen",
"symbol": "Symbol",
"thousand_separator": "Tausendertrennzeichen",
"title": "Währungen"
},
"customization": {
"addresses": {
"address": "Adresse",
"address_setting_updated": "Adresse-Einstellung erfolgreich aktualisiert",
"address_street_1": "Strasse",
"address_street_2": "Zusatz Strasse",
"city": "Stadt",
"company_address": "Firma Adresse",
"company_name": "Name des Unternehmens",
"contact": "Kontakt",
"country": "Land",
"customer_billing_address": "Rechnungsadresse des Kunden",
"customer_shipping_address": "Versand-Adresse des Kunden",
"display_name": "Anzeigename",
"email": "E-Mail",
"insert_fields": "Felder einfügen",
"name": "Name",
"phone": "Telefon",
"primary_contact_name": "Ansprechpartner",
"section_description": "Sie können die Rechnungsadresse und das Versandadressenformat des Kunden festlegen (nur in PDF angezeigt). ",
"state": "Bundesland",
"title": "Adressen",
"website": "Website",
"zip_code": "PLZ"
},
"customization": "Anpassung",
"estimates": {
"autogenerate_estimate_number": "Kostenvoranschlagsnummer automatisch generieren",
"enter_estimate_prefix": "Geben Sie das Kostenvoranschlag Präfix ein",
"estimate_prefix": "Kostenvoranschlag Präfix",
"estimate_setting_description": "Deaktivieren Sie diese Option, wenn Sie nicht jedes Mal, wenn Sie einen neue Kostenvoranschlag erstellen, automatisch eine Schätzung generieren möchten.",
"estimate_setting_updated": "Einstellungen Kostenvoranschläge erfolgreich aktualisiert",
"estimate_settings": "Einstellungen Kostenvoranschlag",
"title": "Kostenvoranschläge"
},
"invoices": {
"autogenerate_invoice_number": "Rechnungsnummer automatisch generieren",
"enter_invoice_prefix": "Rechnungspräfix eingeben",
"invoice_prefix": "Rechnung Präfix",
"invoice_setting_description": "Deaktivieren Sie diese Option, wenn Sie Rechnungsnummern nicht jedes Mal automatisch generieren möchten, wenn Sie eine neue Rechnung erstellen.",
"invoice_setting_updated": "Rechnungseinstellung erfolgreich aktualisiert",
"invoice_settings": "Rechnungseinstellungen",
"notes": "Hinweise",
"terms_and_conditions": "Allgemeine Geschäftsbedingungen",
"title": "Rechnungen"
},
"payments": {
"autogenerate_payment_number": "Zahlungsnummer automatisch generieren",
"enter_payment_prefix": "Zahlungspräfix eingeben",
"payment_prefix": "Zahlung Präfix",
"payment_setting_description": "Deaktivieren Sie diese Option, wenn Sie nicht jedes Mal, wenn Sie eine neue Zahlung erstellen, automatisch Zahlungsnummern generieren möchten.",
"payment_setting_updated": "Zahlungseinstellung erfolgreich aktualisiert",
"payment_settings": "Zahlung Einstellungen",
"title": "Zahlungen"
},
"save": "Speichern",
"updated_message": "Unternehmensinformationen wurden erfolgreich aktualisiert"
},
"date_format": "Datum-Format",
"expense_category": {
"action": "Aktion",
"add_new_category": "Neue Kategorie hinzufügen",
"already_in_use": "Kategorie wird bereits verwendet",
"category_description": "Beschreibung",
"category_name": "Kategorie Name",
"confirm_delete": "Sie können diese Ausgabenkategorie nicht wiederherstellen",
"created_message": "Ausgabenkategorie erfolgreich erstellt",
"deleted_message": "Ausgabenkategorie erfolgreich gelöscht",
"description": "Für das Hinzufügen von Ausgabeneinträgen sind Kategorien erforderlich. Sie können diese Kategorien nach Ihren Wünschen hinzufügen oder entfernen.",
"title": "Kategorien Kosten",
"updated_message": "Ausgabenkategorie erfolgreich aktualisiert"
},
"general": "Allgemeine",
"language": "Sprache",
"mail": {
"driver": "E-Mail Treiber",
"encryption": "E-Mail-Verschlüsselung",
"from_mail": "Von E-Mail-Adresse",
"from_name": "Von E-Mail-Namen",
"host": "E-Mail Mailserver",
"mail_config": "E-Mail-Konfiguration",
"mail_config_desc": "Unten finden Sie das Formular zum Konfigurieren des E-Mail-Treibers zum Senden von E-Mails über die App. Sie können auch Drittanbieter wie Sendgrid, SES usw. konfigurieren.",
"mailgun_domain": "Domain",
"mailgun_endpoint": "Mailgun-Endpunkt",
"mailgun_secret": "Mailgun Verschlüsselung",
"password": "E-Mail-Kennwort",
"port": "E-Mail Port",
"secret": "Verschlüsselung",
"ses_key": "SES-Taste",
"ses_secret": "SES Verschlüsselung",
"username": "E-Mail-Benutzername"
},
"menu_title": {
"account_settings": "Konto-Einstellungen",
"company_information": "Informationen zum Unternehmen",
"customization": "Anpassung",
"expense_category": "Ausgabenkategorien",
"notifications": "Benachrichtigungen",
"preferences": "Einstellungen",
"tax_types": "Steuersätze",
"update_app": "Update App"
},
"notification": {
"description": "Welche E-Mail-Benachrichtigungen möchten Sie erhalten wenn sich etwas ändert?",
"email": "Benachrichtigungen senden an",
"email_save_message": "Email erfolgreich gespeichert",
"estimate_viewed": "Kostenvoranschlag angesehen",
"estimate_viewed_desc": "Wenn Ihr Kunde den gesendeten Kostenvoranschlag anzeigt bekommt.",
"invoice_viewed": "Rechnung angezeigt",
"invoice_viewed_desc": "Wenn Ihr Kunde die gesendete Rechnung anzeigt bekommt.",
"please_enter_email": "Bitte E-Mail eingeben",
"save": "Speichern",
"title": "Benachrichtigung"
},
"pdf": {
"footer_text": "Fußzeile Text",
"pdf_layout": "PDF-Layout",
"title": "PDF-Einstellung"
},
"preferences": {
"currency": "Währung",
"date_format": "Datum-Format",
"discount_per_item": "Rabatt pro Artikel ",
"discount_setting": "Einstellung Rabatt",
"discount_setting_description": "Aktivieren Sie diese Option, wenn Sie einzelnen Rechnungspositionen einen Rabatt hinzufügen möchten. Standardmäßig wird der Rabatt direkt zur Rechnung hinzugefügt.",
"fiscal_year": "Geschäftsjahr",
"general_settings": "Standardeinstellungen für das System.",
"language": "Sprache",
"preference": "Präferenz | Präferenzen",
"save": "Speichern",
"select_date_formate": "select Date Formate",
"select_financial_year": "Geschäftsjahr auswählen",
"select_language": "Sprache auswählen",
"select_time_zone": "Zeitzone auswählen",
"time_zone": "Zeitzone",
"updated_message": "Einstellungen erfolgreich aktualisiert"
},
"primary_currency": "Primäre Währung",
"setting": "Einstellung | Einstellungen",
"tax_types": {
"action": "Aktion",
"add_new_tax": "Neuen Steuersatz hinzufügen",
"add_tax": "Steuersätze hinzufügen",
"already_in_use": "Steuersatz wird bereits verwendet",
"compound_tax": "Compound Tax",
"confirm_delete": "Sie können diesen Steuersatz nicht wiederherstellen",
"created_message": "Steuersatz erfolgreich erstellt",
"deleted_message": "Steuersatz erfolgreich gelöscht",
"description": "Sie können Steuern nach Belieben hinzufügen oder entfernen. Crater unterstützt Steuern auf einzelne Artikel sowie auf die Rechnung.",
"percent": "Prozent",
"tax_name": "Name des Steuersatzes",
"tax_per_item": "Steuersatz pro Artikel",
"tax_setting_description": "Aktivieren Sie diese Option, wenn Sie den Steuersatz zu einzelnen Rechnungspositionen hinzufügen möchten. Standardmäßig wird der Steuersatz direkt zur Rechnung hinzugefügt.",
"tax_settings": "Einstellungen Steuersatz",
"title": "Steuersätze",
"updated_message": "Steuersatz erfolgreich aktualisiert"
},
"timezone": "Zeitzone",
"title": "Einstellungen",
"update_app": {
"avail_update": "Neues Update verfügbar",
"check_update": "Nach Updates suchen",
"current_version": "Aktuelle Version",
"description": "Sie können Crater ganz einfach aktualisieren, indem Sie auf die Schaltfläche unten klicken, um nach einem neuen Update zu suchen.",
"latest_message": "Kein Update verfügbar! Du bist auf der neuesten Version.",
"next_version": "Nächste Version",
"progress_text": "Es dauert nur ein paar Minuten. Bitte aktualisieren Sie den Bildschirm nicht und schließen Sie das Fenster nicht, bevor das Update abgeschlossen ist.",
"title": "Update App",
"update": "Jetzt aktualisieren",
"update_progress": "Update läuft ...",
"update_success": "App wurde aktualisiert! Bitte warten Sie, während Ihr Browserfenster automatisch neu geladen wird."
},
"user_profile": {
"confirm_password": "Kennwort bestätigen",
"email": "E-Mail",
"name": "Name",
"password": "Passwort"
}
},
"tax_types": {
"compound_tax": "zusammengesetzte Steuer",
"description": "Beschreibung",
"name": "Name",
"percent": "Prozent"
},
"validation": {
"address_maxlength": "Die Adresse sollte nicht länger als 255 Zeichen sein.",
"amount_maxlength": "Der Betrag sollte nicht größer als 20 Ziffern sein.",
"amount_minvalue": "Betrag sollte größer als 0 sein.",
"characters_only": "Nur Zeichen.",
"description_maxlength": "Die Beschreibung sollte nicht länger als 255 Zeichen sein.",
"email_already_taken": "Die E-Mail ist bereits vergeben.",
"email_does_not_exist": "Benutzer mit der angegebenen E-Mail existiert nicht",
"email_incorrect": "Falsche E-Mail.",
"item_unit_already_taken": "Die Artikeleinheit wurde bereits vergeben",
"payment_mode_already_taken": "Der Zahlungsmodus wurde bereits verwendet",
"enter_valid_tax_rate": "Geben Sie einen gültige Steuersatz ein",
"invalid_url": "Ungültige URL (Bsp.: http://www.crater.com)",
"maximum_options_error": "Maximal {max} Optionen ausgewählt. Entfernen Sie zuerst eine ausgewählte Option, um eine andere auszuwählen.",
"name_min_length": "Name muss mindestens {count} Zeichen enthalten.",
"not_yet": "Noch erhalten? Erneut senden",
"notes_maxlength": "Notizen sollten nicht länger als 255 Zeichen sein.",
"numbers_only": "Nur Zahlen.",
"password_incorrect": "Passwörter müssen identisch sein",
"password_length": "Passwort muss {count} Zeichen lang sein.",
"password_min_length": "Password muß {count} Zeichen enthalten",
"payment_greater_than_due_amount": "Die eingegebene Zahlung ist mehr als der fällige Betrag dieser Rechnung.",
"payment_greater_than_zero": "Die Zahlung muss größer als 0 sein.",
"prefix_maxlength": "Das Präfix sollte nicht länger als 5 Zeichen sein.",
"price_greater_than_zero": "Preis muss größer als 0 sein.",
"price_maxlength": "Der Preis sollte nicht größer als 20 Ziffern sein.",
"price_minvalue": "Der Preis sollte größer als 0 sein.",
"qty_must_greater_than_zero": "Die Menge muss größer als 0 sein.",
"quantity_maxlength": "Die Menge sollte nicht größer als 20 Ziffern sein.",
"ref_number_maxlength": "Ref Number sollte nicht länger als 255 Zeichen sein.",
"required": "Feld ist erforderlich",
"send_reset_link": "Link zum Zurücksetzen senden"
},
"wizard": {
"account_info": "Account-Informationen",
"account_info_desc": "Die folgenden Details werden zum Erstellen des Hauptadministratorkontos verwendet. Sie können die Details auch jederzeit nach dem Anmelden ändern.",
"address": "Adresse",
"city": "Stadt",
"company_info": "Unternehmensinformationen",
"company_info_desc": "Diese Informationen werden auf Rechnungen angezeigt. Beachten Sie, dass Sie diese später auf der Einstellungsseite bearbeiten können.",
"company_logo": "Firmenlogo",
"company_name": "Firmenname",
"confirm_password": "Passwort bestätigen",
"continue": "Weiter",
"country": "Land",
"currency": "Currency",
"database": {
"app_url": "App-URL",
"connection": "Datenbank Verbindung",
"database": "URL der Seite & Datenbank",
"db_name": "Datenbank Name",
"desc": "Erstellen Sie eine Datenbank auf Ihrem Server und legen Sie die Anmeldeinformationen mithilfe des folgenden Formulars fest.",
"host": "Datenbank Host",
"password": "Datenbank Passwort",
"port": "Datenbank Port",
"username": "Datenbank Benutzername"
},
"date_format": "Datumsformat",
"email": "Email",
"errors": {
"connection_failed": "Datenbankverbindung fehlgeschlagen",
"database_should_be_empty": "Datenbank sollte leer sein",
"database_variables_save_error": "Konfiguration kann nicht in EN.env-Datei geschrieben werden. Bitte überprüfen Sie die Dateiberechtigungen.",
"mail_variables_save_error": "E-Mail-Konfiguration fehlgeschlagen.",
"migrate_failed": "Migration ist Fehlgeschlagen"
},
"fiscal_year": "Geschäftsjahr",
"from_address": "From Address",
"go_back": "Zurück",
"language": "Sprache",
"logo_preview": "Vorschau Logo",
"mail": {
"driver": "E-Mail-Treiber",
"encryption": "E-Mail-Verschlüsselung",
"from_mail": "Von E-Mail-Absenderadresse",
"from_name": "Von E-Mail-Absendername",
"host": "E-Mail-Host",
"mail_config": "E-Mail-Konfiguration",
"mail_config_desc": "Unten finden Sie das Formular zum Konfigurieren des E-Mail-Treibers zum Senden von E-Mails über die App. Sie können auch Drittanbieter wie Sendgrid, SES usw. konfigurieren.",
"mailgun_domain": "Domain",
"mailgun_endpoint": "Mailgun-Endpunkt",
"mailgun_secret": "Mailgun Verschlüsselung",
"password": "E-Mail-Passwort",
"port": "E-Mail-Port",
"secret": "Verschlüsselung",
"ses_key": "SES-Taste",
"ses_secret": "SES Verschlüsselung",
"username": "E-Mail-Benutzername"
},
"name": "Name",
"next": "Next",
"password": "Passwort",
"permissions": {
"permission_confirm_desc": "Prüfung der Berechtigung der Ordner fehlgeschlagen.",
"permission_confirm_title": "Sind Sie sicher, dass Sie fortfahren möchten?",
"permission_desc": "Unten finden Sie eine Liste der Ordnerberechtigungen, die erforderlich sind, damit die App funktioniert. Wenn die Berechtigungsprüfung fehlschlägt, müssen Sie Ihre Ordnerberechtigungen aktualisieren.",
"permissions": "Berechtigungen"
},
"phone": "Telefon",
"preferences": "Einstellungen",
"preferences_desc": "Standardeinstellungen für das System.",
"req": {
"check_req": "Anforderungen prüfen",
"php_req_version": "Php (version {version} erforderlich)",
"system_req": "System Anforderungen",
"system_req_desc": "Crater hat einige Serveranforderungen. Stellen Sie sicher, dass Ihr Server die erforderliche PHP-Version und alle unten genannten Erweiterungen hat."
},
"save_cont": "Speichern und weiter",
"skip": "Überspringen",
"state": "Bundesland",
"street": "Straße1 | Straße2",
"success": {
"database_variables_save_successfully": "Datenbank erfolgreich konfiguriert.",
"mail_variables_save_successfully": "E-Mail erfolgreich konfiguriert"
},
"time_zone": "Zeitzone",
"username": "Benutzername",
"zip_code": "Postleitzahl"
}
}

View File

@ -17,11 +17,17 @@
"save": "Save",
"cancel": "Cancel",
"update": "Update",
"deselect": "Deselect",
"download": "Download",
"from_date": "From Date",
"to_date": "To Date",
"from": "From",
"to": "To",
"sort_by": "Sort By",
"ascending": "Ascending",
"descending": "Descending",
"subject": "Subject",
"message": "Message",
"go_back": "Go Back",
"back_to_login": "Back to Login?",
"home": "Home",
@ -62,6 +68,8 @@
"four_zero_four": "404",
"you_got_lost": "Whoops! You got Lost!",
"go_home": "Go Home",
"test_mail_conf": "Test Mail Configuration",
"send_mail_successfully": "Mail sent successfully",
"setting_updated": "Setting updated successfully",
"select_state": "Select state",
@ -180,7 +188,7 @@
"no_items": "No items yet!",
"list_of_items": "This section will contain the list of items.",
"select_a_unit": "select unit",
"taxes": "Taxes",
"item_attached_message": "Cannot delete an item which is already in use",
"confirm_delete": "You will not be able to recover this Item | You will not be able to recover these Items",
"created_message": "Item created successfully",
@ -225,7 +233,7 @@
"record_payment": "Record Payment",
"add_estimate": "Add Estimate",
"save_estimate": "Save Estimate",
"confirm_conversion": "You want to convert this Estimate into Invoice?",
"confirm_conversion": "This estimate will be used to create a new Invoice.",
"conversion_message": "Invoice created successful",
"confirm_send_estimate": "This estimate will be sent via email to the customer",
"confirm_mark_as_sent": "This estimate will be marked as sent",
@ -329,6 +337,9 @@
"no_matching_invoices": "There are no matching invoices!",
"mark_as_sent_successfully": "Invoice marked as sent successfully",
"send_invoice_successfully": "Invoice sent successfully",
"cloned_successfully": "Invoice cloned successfully",
"clone_invoice": "Clone Invoice",
"confirm_clone": "This invoice will be cloned into a new Invoice",
"item": {
"title": "Item Title",
"description": "Description",
@ -343,7 +354,6 @@
"select_an_item": "Type or click to select an item",
"type_item_description": "Type Item Description (optional)"
},
"payment_attached_message": "One of the selected invoices already have a payment attached to it. Make sure to delete the attached payments first in order to go ahead with the removal",
"confirm_delete": "You will not be able to recover this Invoice | You will not be able to recover these Invoices",
"created_message": "Invoice created successfully",
@ -394,12 +404,18 @@
"edit_payment": "Edit Payment",
"view_payment": "View Payment",
"add_new_payment": "Add New Payment",
"send_payment_receipt": "Send Payment Receipt",
"save_payment": "Save Payment",
"update_payment": "Update Payment",
"payment": "Payment | Payments",
"no_payments": "No payments yet!",
"no_matching_payments": "There are no matching payments!",
"list_of_payments": "This section will contain the list of payments.",
"select_payment_mode": "Select payment mode",
"confirm_send_payment": "This payment will be sent via email to the customer",
"send_payment_successfully": "Payment sent successfully",
"user_email_does_not_exist": "User email does not exist",
"something_went_wrong": "something went wrong",
"confirm_delete": "You will not be able to recover this Payment | You will not be able to recover these Payments",
"created_message": "Payment created successfully",
@ -530,6 +546,7 @@
"menu_title": {
"account_settings": "Account Settings",
"company_information": "Company Information",
"customization": "Customization",
"preferences": "Preferences",
"notifications": "Notifications",
"tax_types": "Tax Types",
@ -598,6 +615,87 @@
"save": "Save",
"updated_message": "Company information updated successfully"
},
"customization": {
"customization": "customization",
"save": "Save",
"addresses": {
"title": "Addresses",
"section_description": "You can set Customer Billing Address and Customer Shipping Address Format (Displayed in PDF only). ",
"customer_billing_address": "Customer Billing Address",
"customer_shipping_address": "Customer Shipping Address",
"company_address": "Company Address",
"insert_fields": "Insert Fields",
"contact": "Contact",
"address": "Address",
"display_name": "Display Name",
"primary_contact_name": "Primary Contact Name",
"email": "Email",
"website": "Website",
"name": "Name",
"country": "Country",
"state": "State",
"city": "City",
"company_name": "Company Name",
"address_street_1": "Address Street 1",
"address_street_2": "Address Street 2",
"phone": "Phone",
"zip_code": "Zip Code",
"address_setting_updated": "Address Setting updated successfully"
},
"updated_message": "Company information updated successfully",
"invoices": {
"title": "Invoices",
"notes": "Notes",
"invoice_prefix": "Invoice Prefix",
"invoice_settings": "Invoice Settings",
"autogenerate_invoice_number": "Auto-generate Invoice Number",
"invoice_setting_description": "Disable this, If you don't wish to auto-generate invoice numbers each time you create a new invoice.",
"enter_invoice_prefix": "Enter invoice prefix",
"terms_and_conditions": "Terms and Conditions",
"invoice_setting_updated": "Invoice Setting updated successfully"
},
"estimates": {
"title": "Estimates",
"estimate_prefix": "Estimate Prefix",
"estimate_settings": "Estimate Settings",
"autogenerate_estimate_number": "Auto-generate Estimate Number",
"estimate_setting_description": "Disable this, If you don't wish to auto-generate estimate numbers each time you create a new estimate.",
"enter_estimate_prefix": "Enter estmiate prefix",
"estimate_setting_updated": "Estimate Setting updated successfully"
},
"payments": {
"title": "Payments",
"payment_prefix": "Payment Prefix",
"payment_settings": "Payment Settings",
"autogenerate_payment_number": "Auto-generate Payment Number",
"payment_setting_description": "Disable this, If you don't wish to auto-generate payment numbers each time you create a new payment.",
"enter_payment_prefix": "Enter Payment Prefix",
"payment_setting_updated": "Payment Setting updated successfully",
"payment_mode": "Payment Mode",
"add_payment_mode": "Add Payment Mode",
"mode_name": "Mode Name",
"payment_mode_added": "Payment Mode Added",
"payment_mode_updated": "Payment Mode Updated",
"payment_mode_confirm_delete":"You will not be able to recover this Payment Mode",
"already_in_use": "Payment Mode is already in use",
"deleted_message": "Payment Mode deleted successfully"
},
"items": {
"title": "Items",
"units": "units",
"add_item_unit": "Add Item Unit",
"unit_name": "Unit Name",
"item_unit_added": "Item Unit Added",
"item_unit_updated": "Item Unit Updated",
"item_unit_confirm_delete":"You will not be able to recover this Item unit",
"already_in_use": "Item Unit is already in use",
"deleted_message": "Item Unit deleted successfully"
}
},
"account_settings": {
"profile_picture": "Profile Picture",
"name": "Name",
@ -666,7 +764,7 @@
"date_format": "Date Format",
"discount_setting": "Discount Setting",
"discount_per_item": "Discount Per Item ",
"discount_setting_description": "Enable this if you want to add Discount to individual invoice items. By default, Discount are added directly to the invoice.",
"discount_setting_description": "Enable this if you want to add Discount to individual invoice items. By default, Discount is added directly to the invoice.",
"save": "Save",
"preference": "Preference | Preferences",
"general_settings": "Default preferences for the system.",
@ -766,7 +864,7 @@
},
"errors": {
"migrate_failed": "Migrate Failed",
"database_variables_save_error": "Unable to connect to the DB with Provided Values.",
"database_variables_save_error": "Cannot write configuration to .env file. Please check its file permissions",
"mail_variables_save_error": "Email configuration failed.",
"connection_failed": "Database connection failed",
"database_should_be_empty": "Database should be empty"
@ -777,7 +875,7 @@
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2019",
"copyright_crater": "Copyright @ Crater - 2020",
"super_simple_invoicing": "Super Simple Invoicing",
"for_freelancer": "for Freelancers &",
"small_businesses": "Small Businesses ",
@ -790,6 +888,8 @@
"email_incorrect": "Incorrect Email.",
"email_already_taken": "The email has already been taken.",
"email_does_not_exist": "User with given email doesn't exist",
"item_unit_already_taken": "This item unit name has already been taken",
"payment_mode_already_taken": "This payment mode name has already been taken",
"send_reset_link": "Send Reset Link",
"not_yet": "Not yet? Send it again",
"password_min_length": "Password must contain {count} characters",
@ -809,9 +909,13 @@
"amount_maxlength": "Amount should not be greater than 20 digits.",
"amount_minvalue": "Amount should be greater than 0.",
"description_maxlength": "Description should not be greater than 255 characters.",
"subject_maxlength": "Subject should not be greater than 100 characters.",
"message_maxlength": "Message should not be greater than 255 characters.",
"maximum_options_error": "Maximum of {max} options selected. First remove a selected option to select another.",
"notes_maxlength": "Notes should not be greater than 255 characters.",
"address_maxlength": "Address should not be greater than 255 characters.",
"ref_number_maxlength": "Ref Number should not be greater than 255 characters."
"ref_number_maxlength": "Ref Number should not be greater than 255 characters.",
"prefix_maxlength": "Prefix should not be greater than 5 characters.",
"something_went_wrong": "something went wrong"
}
}

View File

@ -5,7 +5,7 @@
"items": "Artículos",
"invoices": "Facturas",
"expenses": "Gastos",
"estimates": "Estimadas",
"estimates": "Presupuestos",
"payments": "Pagos",
"reports": "Informes",
"settings": "Configuraciones",
@ -14,44 +14,44 @@
"general": {
"view_pdf": "Ver PDF",
"download_pdf": "Descargar PDF",
"save": "Salvar",
"save": "Guardar",
"cancel": "Cancelar",
"update": "Actualizar",
"download": "Descargar",
"from_date": "Partir de la fecha",
"from_date": "Desde la fecha",
"to_date": "Hasta la fecha",
"from": "De",
"to": "A",
"go_back": "Regresa",
"back_to_login": "¿Atrás para iniciar sesión?",
"home": "Casa",
"go_back": "Volver",
"back_to_login": "¿Volver al inicio de sesión?",
"home": "Inicio",
"filter": "Filtrar",
"delete": "Eliminar",
"edit": "Editar",
"view": "Ver",
"add_new_item": "Agregar ítem nuevo",
"clear_all": "Limpiar todo",
"showing": "Demostración",
"showing": "Mostrando",
"of": "de",
"actions": "Comportamiento",
"subtotal": "TOTAL PARCIAL",
"actions": "Acciones",
"subtotal": "SUBTOTAL",
"discount": "DESCUENTO",
"fixed": "Fija",
"fixed": "Fijo",
"percentage": "Porcentaje",
"tax": "IMPUESTO",
"total_amount": "CANTIDAD TOTAL",
"bill_to": "Cobrar a",
"ship_to": "Envie a",
"due": "Debida",
"draft": "Sequía",
"sent": "Expedida",
"ship_to": "Enviar a",
"due": "Debido",
"draft": "Borrador",
"sent": "Enviado",
"all": "Todas",
"select_all": "Seleccionar todo",
"choose_file": "Haga clic aquí para elegir un archivo.",
"choose_file": "Haga clic aquí para elegir un archivo",
"choose_template": "Elige una plantilla",
"choose": "Escoger",
"remove": "Eliminar",
"powered_by": "Energizado por",
"powered_by": "Impulsado por",
"bytefury": "Bytefury",
"select_a_status": "Selecciona un estado",
"select_a_tax": "Selecciona un impuesto",
@ -61,29 +61,29 @@
"no_tax_found": "¡No se encontraron impuestos!",
"four_zero_four": "404",
"you_got_lost": "Whoops! ¡Te perdiste!",
"go_home": "Vete a casa",
"go_home": "Volver al Inicio",
"setting_updated": "Configuración actualizada con éxito",
"select_state": "Seleccione estado",
"select_state": "Seleccionar estado",
"select_country": "Seleccionar país",
"select_city": "Ciudad selecta",
"select_city": "Seleccionar ciudad",
"street_1": "Calle 1",
"street_2": "Calle # 2",
"action_failed": "Accion: Fallida"
"street_2": "Calle 2",
"action_failed": "Accion Fallida"
},
"dashboard": {
"select_year": "Seleccione año",
"select_year": "Seleccionar año",
"cards": {
"due_amount": "Monto adeudado",
"due_amount": "Cantidad Debida",
"customers": "Clientes",
"invoices": "Facturas",
"estimates": "Estimadas"
"estimates": "Presupuestos"
},
"chart_info": {
"total_sales": "Ventas",
"total_receipts": "Ingresos",
"total_expense": "Gastos",
"net_income": "Lngresos netos",
"net_income": "Ingresos netos",
"year": "Seleccione año"
},
"weekly_invoices": {
@ -96,16 +96,16 @@
"title": "Facturas adeudadas",
"due_on": "Debido a",
"customer": "Cliente",
"amount_due": "Monto adeudado",
"actions": "Comportamiento",
"amount_due": "Cantidad Debida",
"actions": "Acciones",
"view_all": "Ver todo"
},
"recent_estimate_card": {
"title": "Estimaciones recientes",
"title": "Presupuestos recientes",
"date": "Fecha",
"customer": "Cliente",
"amount_due": "Monto adeudado",
"actions": "Comportamiento",
"amount_due": "Cantidad Debida",
"actions": "Acciones",
"view_all": "Ver todo"
}
},
@ -123,16 +123,16 @@
"display_name": "Nombre para mostrar",
"primary_contact_name": "Nombre de contacto primario",
"contact_name": "Nombre de contacto",
"amount_due": "Monto adeudado",
"amount_due": "Cantidad Debida",
"email": "Email",
"address": "Habla a",
"address": "Dirección",
"phone": "Teléfono",
"website": "Sitio web",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"zip_code": "Código postal",
"added_on": "Añadido",
"added_on": "Añadido el",
"action": "Acción",
"password": "Contraseña",
"street_number": "Número de calle",
@ -144,19 +144,14 @@
"new_customer": "Nuevo cliente",
"edit_customer": "Editar cliente",
"basic_info": "Información básica",
"billing_address": "Dirección de Envio",
"billing_address": "Dirección de Facturación",
"shipping_address": "Dirección de Envío",
"copy_billing_address": "Copia de facturación",
"no_customers": "¡Aún no hay clientes!",
"no_customers_found": "No se encontraron clientes!",
"no_customers_found": "¡No se encontraron clientes!",
"list_of_customers": "Esta sección contendrá la lista de clientes.",
"primary_display_name": "Nombre de visualización principal",
"select_state": "Seleccione estado",
"select_country": "Seleccionar país",
"select_city": "Ciudad selecta",
"select_currency": "Seleccione el tipo de moneda",
"street_1": "Calle 1",
"street_2": "Calle 2",
"select_a_customer": "Selecciona un cliente",
"type_or_click": "Escriba o haga clic para seleccionar",
@ -184,7 +179,7 @@
"edit_item": "Editar elemento",
"no_items": "¡Aún no hay artículos!",
"list_of_items": "Esta sección contendrá la lista de artículos.",
"select_a_unit": "seleccione unidad",
"select_a_unit": "seleccionar unidad",
"item_attached_message": "No se puede eliminar un elemento que ya está en uso.",
"confirm_delete": "No podrá recuperar este artículo | No podrás recuperar estos elementos",
@ -193,10 +188,10 @@
"deleted_message": "Elemento eliminado con éxito | Elementos eliminados correctamente"
},
"estimates": {
"title": "Estimadas",
"estimate": "Estimación | Estimados",
"estimates_list": "Lista de estimaciones",
"days": "{días} días",
"title": "Presupuestos",
"estimate": "Presupuesto | Presupuestos",
"estimates_list": "Lista de presupuestos",
"days": "{días} Días",
"months": "{meses} Mes",
"years": "{años} Año",
"all": "Todas",
@ -210,7 +205,7 @@
"total": "Total",
"discount": "Descuento",
"sub_total": "Subtotal",
"estimate_number": "Numero Estimado",
"estimate_number": "Número de Presupuesto",
"ref_number": "Número de referencia",
"contact": "Contacto",
"add_item": "Agregar un artículo",
@ -224,49 +219,52 @@
"notes": "Notas",
"tax": "Impuesto",
"send_estimate": "Enviar presupuesto",
"estimate_template": "Plantilla de estimación",
"estimate_template": "Plantilla de presupuesto",
"convert_to_invoice": "Convertir a factura",
"mark_as_sent": "Marcar como enviado",
"record_payment": "Registro de pago",
"add_estimate": "Agregar presupuesto",
"save_estimate": "Guardar estimación",
"confirm_conversion": "¿Quiere convertir esta estimación en factura?",
"save_estimate": "Guardar presupuesto",
"confirm_conversion": "¿Quiere convertir este presupuesto en una factura?",
"conversion_message": "Conversión exitosa",
"confirm_send_estimate": "Esta estimación se enviará por correo electrónico al cliente",
"confirm_mark_as_sent": "Esta estimación se marcará como enviada",
"confirm_mark_as_accepted": "Esta estimación se marcará como Aceptada",
"confirm_mark_as_rejected": "Esta estimación se marcará como Rechazada",
"mark_as_sent_successfully": "Estimación marcada como enviada correctamente",
"send_estimate_successfully": "Estimación enviada con éxito",
"confirm_send_estimate": "Este presupuesto se enviará por correo electrónico al cliente",
"confirm_mark_as_sent": "Este presupuesto se marcará como enviado",
"confirm_mark_as_accepted": "Este presupuesto se marcará como Aceptado",
"confirm_mark_as_rejected": "Este presupuesto se marcará como Rechazado",
"no_matching_estimates": "¡No hay presupuestos coincidentes!",
"mark_as_sent_successfully": "Presupuesto marcado como enviado correctamente",
"send_estimate_successfully": "Presupuesto enviado con éxito",
"errors": {
"required": "Se requiere campo"
},
"accepted": "Aceptada",
"sent": "Expedida",
"draft": "Sequía",
"declined": "Rechazada",
"new_estimate": "Nueva estimación",
"accepted": "Aceptado",
"sent": "Enviado",
"draft": "Borrador",
"declined": "Rechazado",
"new_estimate": "Nuevo presupuesto",
"add_new_estimate": "Añadir nuevo presupuesto",
"update_Estimate": "Actualizar presupuesto",
"edit_estimate": "Editar estimación",
"edit_estimate": "Editar presupuesto",
"items": "artículos",
"Estimate": "Estimación | Estimados",
"Estimate": "Presupuestos | Presupuestos",
"add_new_tax": "Agregar nuevo impuesto",
"no_estimates": "¡Aún no hay estimaciones!",
"list_of_estimates": "Esta sección contendrá la lista de estimaciones.",
"no_estimates": "¡Aún no hay presupuestos!",
"list_of_estimates": "Esta sección contendrá la lista de presupuestos.",
"mark_as_rejected": "Marcar como rechazado",
"mark_as_accepted": "Marcar como aceptado",
"marked_as_accepted_message": "Estimación marcada como aceptada",
"marked_as_rejected_message": "Estimación marcada como rechazada",
"confirm_delete": "No podrá recuperar esta estimación | No podrá recuperar estas estimaciones",
"created_message": "Estimación creada con éxito",
"updated_message": "Estimación actualizada con éxito",
"deleted_message": "Estimación eliminada con éxito | Estimaciones eliminadas exitosamente",
"marked_as_accepted_message": "Presupuesto marcado como aceptado",
"marked_as_rejected_message": "Presupuesto marcado como rechazado",
"confirm_delete": "No podrá recuperar este presupuesto | No podrá recuperar estos presupuestos",
"created_message": "Presupuesto creada con éxito",
"updated_message": "Presupuesto actualizada con éxito",
"deleted_message": "Presupuesto eliminada con éxito | Presupuestos eliminadas exitosamente",
"user_email_does_not_exist": "El email del usuario no existe",
"something_went_wrong": "Algo fue mal",
"item": {
"title": "Título del artículo",
"description": "Descripción",
"quantity": "Quantity",
"quantity": "Cantidad",
"price": "Precio",
"discount": "Descuento",
"total": "Total",
@ -275,13 +273,13 @@
"tax": "Impuesto",
"amount": "Cantidad",
"select_an_item": "Escriba o haga clic para seleccionar un elemento",
"type_item_description": "Tipo Elemento Descripción (opcional)"
"type_item_description": "Descripción del tipo de elemento(opcional)"
}
},
"invoices": {
"title": "Facturas",
"invoices_list": "Lista de facturas",
"days": "{días} días",
"days": "{días} Días",
"months": "{meses} Mes",
"years": "{años} Año",
"all": "Todas",
@ -309,16 +307,17 @@
"action": "Acción",
"notes": "Notas",
"view": "Ver",
"send_invoice": "Enviará la factura",
"send_invoice": "Enviar la factura",
"invoice_template": "Plantilla de factura",
"template": "Modelo",
"mark_as_sent": "Marcar como enviado",
"mark_as_sent": "Marcar como enviada",
"invoice_mark_as_sent": "Esta factura se marcará como enviada",
"confirm_send_invoice": "Esta factura será enviada por email al cliente",
"confirm_send": "Estas facturas se enviarán por correo electrónico al cliente.",
"invoice_date": "Fecha de la factura",
"record_payment": "Registro de pago",
"add_new_invoice": "Añadir nueva factura",
"update_expense": "Gastos de actualización",
"update_expense": "Actualizar gasto",
"edit_invoice": "Editar factura",
"new_invoice": "Nueva factura",
"save_invoice": "Guardar factura",
@ -327,6 +326,7 @@
"no_invoices": "¡Aún no hay facturas!",
"list_of_invoices": "Esta sección contendrá la lista de facturas.",
"select_invoice": "Seleccionar factura",
"no_matching_invoices": "¡No hay facturas coincidentes con la selección!",
"mark_as_sent_successfully": "Factura marcada como enviada con éxito",
"send_invoice_successfully": "Factura enviada exitosamente",
"item": {
@ -341,7 +341,7 @@
"tax": "Impuesto",
"amount": "Cantidad",
"select_an_item": "Escriba o haga clic para seleccionar un elemento",
"type_item_description": "Tipo Elemento Descripción (opcional)"
"type_item_description": "Descripción del tipo de elemento (opcional)"
},
"payment_attached_message": "Una de las facturas seleccionadas ya tiene un pago adjunto. Asegúrese de eliminar primero los pagos adjuntos para continuar con la eliminación",
"confirm_delete": "No podrá recuperar esta factura | No podrá recuperar estas facturas",
@ -349,7 +349,9 @@
"updated_message": "Factura actualizada exitosamente",
"deleted_message": "Factura eliminada con éxito | Facturas borradas exitosamente",
"marked_as_sent_message": "Factura marcada como enviada con éxito",
"invalid_due_amount_message": "El pago ingresado es mayor que el monto total adeudado por esta factura. Por favor verifique y vuelva a intentar"
"user_email_does_not_exist": "El email del usuario no existe",
"something_went_wrong": "Algo fue mal",
"invalid_due_amount_message": "El pago ingresado es mayor que la cantidad total debida por esta factura. Por favor verificalo y vuelve a intentarlo"
},
"credit_notes": {
"title": "Notas de credito",
@ -395,6 +397,7 @@
"update_payment": "Actualizar pago",
"payment": "Pago | Pagos",
"no_payments": "¡Aún no hay pagos!",
"no_matching_payments": "¡No hay pagos equivalentes!",
"list_of_payments": "Esta sección contendrá la lista de pagos.",
"select_payment_mode": "Seleccionar modo de pago",
@ -410,7 +413,7 @@
"expense_title": "Título",
"contact": "Contacto",
"category": "Categoría",
"from_date": "Partir de la fecha",
"from_date": "Desde la fecha",
"to_date": "Hasta la fecha",
"expense_date": "Fecha",
"description": "Descripción",
@ -422,13 +425,13 @@
"date": "Fecha de gastos",
"add_expense": "Añadir gastos",
"add_new_expense": "Añadir nuevo gasto",
"save_expense": "Ahorre gastos",
"update_expense": "Gastos de actualización",
"save_expense": "Guardar gasto",
"update_expense": "Actualizar gasto",
"download_receipt": "Descargar recibo",
"edit_expense": "Editar gasto",
"new_expense": "Nuevo gasto",
"expense": "Gastos | Gastos",
"no_expenses": "No hay gastos todavía!",
"no_expenses": "¡No hay gastos todavía!",
"list_of_expenses": "Esta sección contendrá la lista de gastos.",
"confirm_delete": "No podrá recuperar este gasto | No podrá recuperar estos gastos",
@ -451,19 +454,20 @@
"login": {
"email": "Email",
"password": "Contraseña",
"forgot_password": "¿Se te olvidó tu contraseña?",
"or_signIn_with": "o Inicie sesión con",
"forgot_password": "¿Olvidaste tu contraseña?",
"or_signIn_with": "o Inicia sesión con",
"login": "Iniciar sesión",
"register": "Registro",
"reset_password": "Restablecer la contraseña",
"enter_email": "Ingrese correo electrónico",
"enter_password": "Introducir la contraseña",
"retype_password": "Retype Password",
"password_reset_successfully": "Contraseña reestablecida con éxito",
"enter_email": "Escriba el correo electrónico",
"enter_password": "Escriba la contraseña",
"retype_password": "Reescriba la contraseña",
"login_placeholder": "mail@example.com"
},
"reports": {
"title": "Reporte",
"from_date": "Partir de la fecha",
"title": "Informe",
"from_date": "A partir de la fecha",
"to_date": "Hasta la fecha",
"status": "Estado",
"paid": "Pagada",
@ -475,20 +479,20 @@
"profit_loss": {
"profit_loss": "Pérdida de beneficios",
"to_date": "Hasta la fecha",
"from_date": "Partir de la fecha",
"from_date": "A partir de la fecha",
"date_range": "Seleccionar rango de fechas"
},
"sales": {
"sales": "Ventas",
"date_range": "Seleccionar rango de fechas",
"to_date": "Hasta la fecha",
"from_date": "Partir de la fecha",
"from_date": "A partir de la fecha",
"report_type": "Tipo de informe"
},
"taxes": {
"taxes": "Impuestos",
"to_date": "Hasta la fecha",
"from_date": "Partir de la fecha",
"from_date": "A partir de la fecha",
"date_range": "Seleccionar rango de fechas"
},
"errors": {
@ -503,10 +507,10 @@
"status": "Estado"
},
"estimates": {
"estimate": "Estimar",
"estimate_date": "Fecha estimada",
"estimate": "Presupuestar",
"estimate_date": "Fecha presupuesto",
"due_date": "Fecha de vencimiento",
"estimate_number": "Numero Estimado",
"estimate_number": "Número de Presupuesto",
"ref_number": "Número de referencia",
"amount": "Cantidad",
"contact_name": "Nombre de contacto",
@ -518,7 +522,7 @@
"date": "Fecha",
"amount": "Cantidad",
"to_date": "Hasta la fecha",
"from_date": "Partir de la fecha",
"from_date": "A partir de la fecha",
"date_range": "Seleccionar rango de fechas"
}
},
@ -526,6 +530,7 @@
"menu_title": {
"account_settings": "Configuraciones de la cuenta",
"company_information": "Información de la empresa",
"customization": "Personalización",
"preferences": "Preferencias",
"notifications": "Notificaciones",
"tax_types": "Tipos de impuestos",
@ -548,7 +553,7 @@
"code": "Código",
"symbol": "Símbolo",
"precision": "Precisión",
"thousand_separator": "Mil separadores",
"thousand_separator": "Separador de miles",
"decimal_separator": "Separador decimal",
"position": "Posición",
"position_of_symbol": "Posición del símbolo",
@ -566,9 +571,9 @@
"username": "Nombre de usuario de correo",
"mailgun_secret": "Mailgun Secreto",
"mailgun_domain": "Domino",
"mailgun_endpoint": "Mailgun Punto Final",
"ses_secret": "SES Secreto",
"ses_key": "SES llave",
"mailgun_endpoint": "Mailgun endpoint",
"ses_secret": "Secreto SES",
"ses_key": "Clave SES",
"from_name": "Del nombre del correo",
"from_mail": "Desde la dirección de correo",
"mail_config": "Configuración de correo",
@ -582,18 +587,79 @@
},
"company_info": {
"company_info": "Información de la compañía",
"company_name": "nombre de empresa",
"company_name": "Nombre de Empresa",
"company_logo": "Logo de la compañía",
"section_description": "Información sobre su empresa que se mostrará en las facturas, estimaciones y otros documentos creados por Crater.",
"section_description": "Información sobre su empresa que se mostrará en las facturas, presupuestos y otros documentos creados por Crater.",
"phone": "Teléfono",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"address": "Habla a",
"address": "Dirección",
"zip": "Código Postal",
"save": "Salvar",
"save": "Guardar",
"updated_message": "Información de la empresa actualizada con éxito"
},
"customization": {
"customization": "Personalización",
"save": "Guardar",
"addresses": {
"title": "Direcciones",
"section_description": "Puede configurar la Dirección de facturación del cliente y el Formato de dirección de envío del cliente (solo se muestra en PDF).",
"customer_billing_address": "Dirección de facturación del cliente",
"customer_shipping_address": "Dirección de envío del cliente",
"company_address": "Dirección de la compañia",
"insert_fields": "Insertar campos",
"contact": "Contacto",
"address": "Dirección",
"display_name": "Nombre para mostrar",
"primary_contact_name": "Nombre de contacto principal",
"email": "Email",
"website": "Sitio web",
"name": "Nombre",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"company_name": "Nombre de la compañia",
"address_street_1": "Dirección de la calle 1",
"address_street_2": "Dirección de la calle 2",
"phone": "Telefono",
"zip_code": "Codigo postal",
"address_setting_updated": "Configuración de dirección actualizada correctamente"
},
"updated_message": "Información de la empresa actualizada con éxito",
"invoices": {
"title": "Facturas",
"notes": "Notas",
"invoice_prefix": "Prefijo de las facturas",
"invoice_settings": "Ajustes de facturas",
"autogenerate_invoice_number": "Autogenerar número de factura",
"invoice_setting_description": "Desactive esto, si no desea generar automáticamente números de factura cada vez que cree una nueva factura.",
"enter_invoice_prefix": "Introduzca el prefijo de factura",
"terms_and_conditions": "Términos y Condiciones",
"invoice_setting_updated": "Configuración de factura actualizada correctamente"
},
"estimates": {
"title": "Estimaciones",
"estimate_prefix": "Prefijo de los presupuestos",
"estimate_settings": "Ajustes de presupuestos",
"autogenerate_estimate_number": "Autogenerar número de presupuesto",
"estimate_setting_description": "Desactive esto, si no desea generar automáticamente números de presupuesto cada vez que cree un nuevo presupuesto.",
"enter_estimate_prefix": "Introduzca el prefijo de presupuesto",
"estimate_setting_updated": "Configuración de presupuestos actualizada correctamente"
},
"payments": {
"title": "Payments",
"payment_prefix": "Prefijo de los pagos",
"payment_settings": "Ajustes de pagos",
"autogenerate_payment_number": "Autogenerar número de pago",
"payment_setting_description": "Desactive esto, si no desea generar automáticamente números de pago cada vez que cree un nuevo pago.",
"enter_payment_prefix": "Introduzca el prefijo de pago",
"payment_setting_updated": "Configuración de pagos actualizada correctamente"
}
},
"account_settings": {
"profile_picture": "Foto de perfil",
"name": "Nombre",
@ -601,7 +667,7 @@
"password": "Contraseña",
"confirm_password": "Confirmar contraseña",
"account_settings": "Configuraciones de la cuenta",
"save": "Salvar",
"save": "Guardar",
"section_description": "Puede actualizar su nombre, correo electrónico y contraseña utilizando el siguiente formulario.",
"updated_message": "Configuración de la cuenta actualizada correctamente"
},
@ -616,10 +682,10 @@
"email": "Enviar notificaciones a",
"description": "¿Qué notificaciones por correo electrónico le gustaría recibir cuando algo cambia?",
"invoice_viewed": "Factura vista",
"invoice_viewed_desc": "Cuando su cliente ve la factura enviada a través del panel de control del cráter.",
"estimate_viewed": "Estimación vista",
"estimate_viewed_desc": "Cuando su cliente ve la estimación enviada a través del panel de control del cráter.",
"save": "Salvar",
"invoice_viewed_desc": "Cuando su cliente vio la factura enviada a través del panel de control de Crater.",
"estimate_viewed": "Presupuesto visto",
"estimate_viewed_desc": "Cuando su cliente vio el presupuesto enviado a través del panel de control de Crater.",
"save": "Guardar",
"email_save_message": "Correo electrónico guardado con éxito",
"please_enter_email": "Por favor, introduzca su correo electrónico"
},
@ -630,11 +696,11 @@
"add_new_tax": "Agregar nuevo impuesto",
"tax_settings": "Configuraciones de impuestos",
"tax_per_item": "Impuesto por artículo",
"tax_name": "Nombre fiscal",
"tax_name": "Nombre del impuesto",
"compound_tax": "Impuesto compuesto",
"percent": "Por ciento",
"percent": "Porcentaje",
"action": "Acción",
"tax_setting_description": "Habilítelo si desea agregar impuestos a artículos de factura individuales. Por defecto, los impuestos se agregan directamente a la factura.",
"tax_setting_description": "Habilítelo si desea agregar impuestos a artículos de factura de forma individual. Por defecto, los impuestos se agregan directamente a la factura.",
"created_message": "Tipo de impuesto creado con éxito",
"updated_message": "Tipo de impuesto actualizado correctamente",
"deleted_message": "Tipo de impuesto eliminado correctamente",
@ -663,7 +729,7 @@
"discount_setting": "Ajuste de descuento",
"discount_per_item": "Descuento por artículo",
"discount_setting_description": "Habilítelo si desea agregar Descuento a artículos de factura individuales. Por defecto, los descuentos se agregan directamente a la factura.",
"save": "Salvar",
"save": "Guardar",
"preference": "Preferencia | Preferencias",
"general_settings": "Preferencias predeterminadas para el sistema.",
"updated_message": "Preferencias actualizadas exitosamente",
@ -693,7 +759,7 @@
"email": "Email",
"password": "Contraseña",
"confirm_password": "Confirmar contraseña",
"save_cont": "Guardar Continuar",
"save_cont": "Guardar y continuar",
"company_info": "Información de la empresa",
"company_info_desc": "Esta información se mostrará en las facturas. Tenga en cuenta que puede editar esto más adelante en la página de configuración.",
"company_name": "nombre de empresa",
@ -704,8 +770,8 @@
"country": "País",
"state": "Estado",
"city": "Ciudad",
"address": "Habla a",
"street": "Calle1 | Calle # 2",
"address": "Dirección",
"street": "Calle1 | Calle2",
"phone": "Teléfono",
"zip_code": "Código postal",
"go_back": "Regresa",
@ -714,16 +780,17 @@
"time_zone": "Zona horaria",
"fiscal_year": "Año financiero",
"date_format": "Formato de fecha",
"from_address": "De la Dirección",
"from_address": "Desde la Dirección",
"username": "Nombre de usuario",
"next": "Próximo",
"continue": "Hacer continuación",
"next": "Siguiente",
"continue": "Continuar",
"skip": "Saltar",
"database": {
"database": "URL del sitio y base de datose",
"connection": "Conexión de base de datos",
"host": "Database Host",
"port": "Host de base de datos",
"password": "Contraseña de base de datos",
"host": "Host de la base de datos",
"port": "Puerto de la base de datos",
"password": "Contraseña de la base de datos",
"app_url": "URL de la aplicación",
"username": "Nombre de usuario de la base de datos",
"db_name": "Nombre de la base de datos",
@ -731,7 +798,7 @@
},
"permissions": {
"permissions": "Permisos",
"permission_confirm_title": "Estás seguro de que quieres continuar?",
"permission_confirm_title": "¿Estás seguro de que quieres continuar?",
"permission_confirm_desc": "Error de verificación de permisos de carpeta",
"permission_desc": "A continuación se muestra la lista de permisos de carpeta necesarios para que la aplicación funcione. Si la verificación de permisos falla, asegúrese de actualizar los permisos de su carpeta."
},
@ -740,16 +807,16 @@
"port": "Puerto de correo",
"driver": "Conductor de correo",
"secret": "Secreto",
"mailgun_secret": "Mailgun Secreto",
"mailgun_domain": "Dominio",
"mailgun_endpoint": "Mailgun endpoint",
"password": "Contraseña de correo",
"username": "Nombre de usuario de correo",
"mailgun_secret": "Mailgun Secreto",
"mailgun_domain": "Domino",
"mailgun_endpoint": "Mailgun Punto Final",
"ses_secret": "SES Secreto",
"ses_key": "SES llave",
"ses_secret": "Secreto SES",
"ses_key": "Clave SES",
"mail_config": "Configuración de correo",
"from_name": "Del nombre del correo",
"from_mail": "Desde la dirección de correo",
"mail_config": "Configuración de correo",
"encryption": "Cifrado de correo",
"mail_config_desc": "Los detalles a continuación se utilizarán para actualizar el entorno de correo. También puede cambiar los detalles en cualquier momento después de iniciar sesión."
},
@ -763,7 +830,8 @@
"migrate_failed": "La migración falló",
"database_variables_save_error": "No se puede conectar a la base de datos con los valores proporcionados.",
"mail_variables_save_error": "La configuración del correo electrónico ha fallado.",
"connection_failed": "Conexión de base de datos fallida"
"connection_failed": "Conexión de base de datos fallida",
"database_should_be_empty": "La base de datos debe estar vacía"
},
"success": {
"mail_variables_save_successfully": "Correo electrónico configurado correctamente",
@ -771,32 +839,33 @@
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2019",
"copyright_crater": "Copyright @ Crater - 2020",
"super_simple_invoicing": "Facturación super simple",
"for_freelancer": "para autónomos y",
"small_businesses": "Pequeñas empresas",
"crater_help": "Crater te ayuda a rastrear gastos, registrar pagos y generar hermosos",
"small_businesses": "pequeñas empresas",
"crater_help": "Crater te ayuda a rastrear gastos, registrar pagos y generar hermosas",
"invoices_and_estimates": "facturas y presupuestos con capacidad para elegir múltiples plantillas."
},
"validation": {
"invalid_url": "URL no válida (por ejemplo, http://www.crater.com)",
"required": "Se requiere campo",
"email_incorrect": "Email incorrecto.",
"email_does_not_exist": " Usuario con correo electrónico dado no existe",
"send_reset_link": "Enviar restablecer enlace",
"not_yet": "¿Aún no? Envialo de nuevo",
"email_already_taken": "Este email ya está en uso",
"email_does_not_exist": "El usuario con el correo electrónico dado no existe",
"send_reset_link": "Enviar enlace de restablecimiento",
"payment_mode_already_taken": "El modo de pago ya ha sido tomado",
"not_yet": "¿Aún no? Envíalo de nuevo",
"password_min_length": "La contraseña debe contener {count} caracteres",
"name_min_length": "El nombre debe tener al menos {count} letras.",
"enter_valid_tax_rate": "Ingrese una tasa impositiva válida",
"numbers_only": "Solo numeros.",
"characters_only": "Solo personajes.",
"numbers_only": "Solo números.",
"characters_only": "Solo caracteres.",
"password_incorrect": "Las contraseñas deben ser idénticas",
"password_length": "La contraseña debe tener 5 caracteres de longitud.",
"qty_must_greater_than_zero": "La cantidad debe ser mayor que cero.",
"price_greater_than_zero": "El precio debe ser mayor que cero.",
"payment_greater_than_zero": "El pago debe ser mayor que cero.",
"payment_greater_than_due_amount": "El pago ingresado es mayor al monto adeudado de esta factura.",
"payment_greater_than_due_amount": "El pago ingresado es mayor a la cantidad debida de esta factura.",
"quantity_maxlength": "La cantidad no debe ser mayor de 20 dígitos.",
"price_maxlength": "El precio no debe ser mayor de 20 dígitos.",
"price_minvalue": "El precio debe ser mayor que 0 dígitos",
@ -806,6 +875,7 @@
"maximum_options_error": "Máximo de {max} opciones seleccionadas. Primero elimine una opción seleccionada para seleccionar otra.",
"notes_maxlength": "Las notas no deben tener más de 255 caracteres.",
"address_maxlength": "La dirección no debe tener más de 255 caracteres.",
"ref_number_maxlength": "El número de referencia no debe tener más de 255 caracteres."
"ref_number_maxlength": "El número de referencia no debe tener más de 255 caracteres.",
"prefix_maxlength": "El prefijo no debe tener más de 5 caracteres."
}
}

View File

@ -1,11 +1,11 @@
{
"navigation": {
"dashboard": "Tableau de bord",
"customers": "Cliente",
"customers": "Clients",
"items": "Articles",
"invoices": "Factures",
"expenses": "Les dépenses",
"estimates": "Estimations",
"expenses": "Dépenses",
"estimates": "Devis",
"payments": "Paiements",
"reports": "Rapports",
"settings": "Paramètres",
@ -14,11 +14,11 @@
"general": {
"view_pdf": "Voir PDF",
"download_pdf": "Télécharger le PDF",
"save": "sauver",
"save": "Sauvegarder",
"cancel": "Annuler",
"update": "Mise à jour",
"download": "Télécharger",
"from_date": "Partir de la date",
"from_date": "A partir de la date",
"to_date": "À ce jour",
"from": "De",
"to": "À",
@ -51,12 +51,12 @@
"choose_template": "Choisissez un modèle",
"choose": "Choisir",
"remove": "Retirer",
"powered_by": "Alimenté par",
"powered_by": "Propulsé par",
"bytefury": "Bytefury",
"select_a_status": "Sélectionnez un statut",
"select_a_tax": "Sélectionnez une taxe",
"search": "Chercher",
"are_you_sure": "Êtes-vous sûr?",
"are_you_sure": "Êtes-vous sûr ?",
"list_is_empty": "La liste est vide",
"no_tax_found": "Aucune taxe trouvée!",
"four_zero_four": "404",
@ -72,19 +72,19 @@
"action_failed": "Action : échoué"
},
"dashboard": {
"select_year": "Sélectionnez lannée",
"select_year": "Sélectionnez l'année",
"cards": {
"due_amount": "Montant dû",
"customers": "Les clients",
"customers": "Clients",
"invoices": "Factures",
"estimates": "Estimations"
"estimates": "Devis"
},
"chart_info": {
"total_sales": "Ventes",
"total_receipts": "Reçus",
"total_expense": "Les dépenses",
"total_expense": "Dépenses",
"net_income": "Revenu net",
"year": "Sélectionnez lannée"
"year": "Sélectionnez l'année"
},
"weekly_invoices": {
"title": "Factures hebdomadaires"
@ -94,16 +94,16 @@
},
"recent_invoices_card": {
"title": "Factures dues",
"due_on": "Due On",
"customer": "Cliente",
"due_on": "Due le",
"customer": "Client",
"amount_due": "Montant dû",
"actions": "Actions",
"view_all": "Voir tout"
},
"recent_estimate_card": {
"title": "Estimations récentes",
"title": "Devis récents",
"date": "Date",
"customer": "Cliente",
"customer": "Client",
"amount_due": "Montant dû",
"actions": "Actions",
"view_all": "Voir tout"
@ -112,16 +112,16 @@
"tax_types": {
"name": "Nom",
"description": "La description",
"percent": "Pour cent",
"percent": "Pourcent",
"compound_tax": "Taxe composée"
},
"customers": {
"title": "Les clients",
"title": "Clients",
"add_customer": "Ajouter un client",
"contacts_list": "Liste de clients",
"name": "Nom",
"display_name": "Afficher un nom",
"primary_contact_name": "Nom du contact principal",
"display_name": "Statut et Nom de la société",
"primary_contact_name": "Nom du contact",
"contact_name": "Nom du contact",
"amount_due": "Montant dû",
"email": "Email",
@ -155,8 +155,8 @@
"select_country": "Choisissez le pays",
"select_city": "Sélectionnez une ville",
"select_currency": "Sélectionnez la devise",
"street_1": "Rue 1",
"street_2": "Rue 2",
"street_1": "Adresse",
"street_2": "Adresse complémentaire",
"select_a_customer": "Sélectionnez un client",
"type_or_click": "Tapez ou cliquez pour sélectionner",
@ -184,7 +184,7 @@
"edit_item": "Modifier larticle",
"no_items": "Aucun article pour le moment!",
"list_of_items": "Cette section contiendra la liste des éléments.",
"select_a_unit": "sélectionner lunité",
"select_a_unit": "Sélectionnez l'unité",
"item_attached_message": "Impossible de supprimer un élément déjà utilisé",
"confirm_delete": "Vous ne pourrez pas récupérer cet article | Vous ne pourrez pas récupérer ces objets",
@ -193,16 +193,16 @@
"deleted_message": "Élément supprimé avec succès | Éléments supprimés avec succès"
},
"estimates": {
"title": "Estimations",
"estimate": "Estimation | Estimations",
"estimates_list": "Liste des estimations",
"title": "Devis",
"estimate": "Devis | Devis",
"estimates_list": "Liste des devis",
"days": "{jours} jours",
"months": "{mois} mois",
"years": "{années} Année",
"all": "Toute",
"all": "Tout",
"paid": "Payé",
"unpaid": "Non payé",
"customer": "CLIENTE CLIENT",
"customer": "CLIENT CLIENT",
"ref_no": "REF NO.",
"number": "NOMBRE",
"amount_due": "MONTANT DÛ",
@ -223,29 +223,29 @@
"action": "action",
"notes": "Remarques",
"tax": "Impôt",
"estimate_template": "Modèle destimation",
"estimate_template": "Modèle de devis",
"convert_to_invoice": "Convertir en facture",
"mark_as_sent": "Marquer comme envoyé",
"send_estimate": "Envoyer une estimation",
"send_estimate": "Envoyer un devis",
"record_payment": "Record de paiement",
"add_estimate": "Ajouter une estimation",
"save_estimate": "Sauvegarder lestimation",
"confirm_conversion": "Vous souhaitez convertir cette estimation en facture?",
"add_estimate": "Ajouter un devis",
"save_estimate": "Sauvegarder le devis",
"confirm_conversion": "Vous souhaitez convertir ce devis en facture?",
"conversion_message": "Conversion réussie",
"confirm_send_estimate": "Cette estimation sera envoyée par courrier électronique au client.",
"confirm_mark_as_sent": "Cette estimation sera marquée comme envoyé",
"confirm_mark_as_accepted": "Cette estimation sera marquée comme acceptée",
"confirm_mark_as_rejected": "Cette estimation sera marquée comme Rejetée",
"mark_as_sent_successfully": "Estimation marquée comme envoyée avec succès",
"send_estimate_successfully": "Estimation envoyée avec succès",
"confirm_send_estimate": "Ce devis sera envoyée par courrier électronique au client.",
"confirm_mark_as_sent": "Ce devis sera marquée comme envoyé",
"confirm_mark_as_accepted": "Ce devis sera marquée comme acceptée",
"confirm_mark_as_rejected": "Ce devis sera marquée comme Rejetée",
"mark_as_sent_successfully": "Devis marquée comme envoyée avec succès",
"send_estimate_successfully": "Devis envoyée avec succès",
"errors": {
"required": "Champ requis"
},
"accepted": "Accepté",
"sent": "Envoyée",
"draft": "Brouillon",
"declined": "Diminué",
"new_estimate": "Nouvelle estimation",
"declined": "Refusé",
"new_estimate": "Nouveau devis",
"add_new_estimate": "Ajouter une nouvelle estimation",
"update_Estimate": "Mise à jour de lestimation",
"edit_estimate": "Modifier lestimation",
@ -347,7 +347,7 @@
"confirm_delete": "Vous ne pourrez pas récupérer cette facture | Vous ne pourrez pas récupérer ces factures",
"created_message": "Facture créée avec succès",
"updated_message": "Facture mise à jour avec succès",
"deleted_message": "Invoice deleted successfully | Invoices deleted successfully",
"deleted_message": "La Facture a été supprimée ! | Les Factures ont été supprimées !",
"marked_as_sent_message": "Facture supprimée avec succès | Factures supprimées avec succès",
"invalid_due_amount_message": "Le paiement entré est supérieur au montant total dû pour cette facture. Veuillez vérifier et réessayer"
},
@ -378,9 +378,9 @@
"title": "Paiements",
"payments_list": "Liste de paiements",
"record_payment": "Record de paiement",
"customer": "Cliente Client",
"customer": "Client Client",
"date": "Date",
"amount": "Montante Montant",
"amount": "Montant Montant",
"action": "action",
"payment_number": "Numéro de paiement",
"payment_mode": "Mode de paiement",
@ -395,6 +395,7 @@
"update_payment": "Mettre à jour le paiement",
"payment": "Paiement | Paiements",
"no_payments": "Aucun paiement pour le moment!",
"no_matching_payments": "Il n'y a aucun paiement correspondant!",
"list_of_payments": "Cette section contiendra la liste des paiements",
"select_payment_mode": "Sélectionnez le mode de paiement",
@ -405,17 +406,17 @@
"invalid_amount_message": "Le montant du paiement est invalide"
},
"expenses": {
"title": "Les dépenses",
"title": "Dépenses",
"expenses_list": "Liste des dépenses",
"expense_title": "Titre",
"contact": "Contact",
"category": "Catégorie",
"from_date": "Partir de la date",
"from_date": "A partir de la date",
"to_date": "À ce jour",
"expense_date": "Date",
"description": "La description",
"receipt": "Le reçu",
"amount": "Montante Montant",
"amount": "Montant Montant",
"action": "action",
"note": "Remarque",
"category_id": "Identifiant de catégorie",
@ -440,7 +441,7 @@
"title": "Titre",
"name": "Nom",
"description": "La description",
"amount": "Montante Montant",
"amount": "Montant Montant",
"actions": "Actions",
"add_category": "ajouter une catégorie",
"new_category": "Nouvelle catégorie",
@ -463,7 +464,7 @@
},
"reports": {
"title": "rapport",
"from_date": "Partir de la date",
"from_date": "A partir de la date",
"to_date": "À ce jour",
"status": "Statut",
"paid": "Payé",
@ -482,20 +483,20 @@
"sales": "Ventes",
"date_range": "Sélectionner une plage de dates",
"to_date": "À ce jour",
"from_date": "Partir de la date",
"from_date": "A partir de la date",
"report_type": "Type de rapport"
},
"taxes": {
"taxes": "Les taxes",
"to_date": "À ce jour",
"from_date": "Partir de la date",
"from_date": "A partir de la date",
"date_range": "Sélectionner une plage de dates"
},
"errors": {
"required": "Champ requis"
},
"invoices": {
"invoice": "Facture dachat",
"invoice": "Facture d'achat",
"invoice_date": "Date de facturation",
"due_date": "Date déchéance",
"amount": "Montante ",
@ -503,22 +504,22 @@
"status": "Statut"
},
"estimates": {
"estimate": "Estimation",
"estimate_date": "Date destimation",
"due_date": "Date déchéance",
"estimate_number": "Numéro destimation",
"estimate": "Devis",
"estimate_date": "Date du devis",
"due_date": "Date d'échéance",
"estimate_number": "Numéro d'estimation",
"ref_number": "Numéro de ref",
"amount": "Montante",
"amount": "Montant",
"contact_name": "Nom du contact",
"status": "Statut"
},
"expenses": {
"expenses": "Les dépenses",
"expenses": "Dépenses",
"category": "Catégorie",
"date": "Date",
"amount": "Montante",
"amount": "Montant",
"to_date": "À ce jour",
"from_date": "Partir de la date",
"from_date": "A partir de la date",
"date_range": "Sélectionner une plage de dates"
}
},
@ -535,7 +536,7 @@
"title": "Paramètres",
"setting": "Paramètres | Paramètres",
"general": "Générale",
"language": "La langue",
"language": "Langue",
"primary_currency": "Devise principale",
"timezone": "Fuseau horaire",
"date_format": "Format de date",
@ -558,18 +559,18 @@
"add_currency": "Ajouter une devise"
},
"mail": {
"host": "Mail Host",
"port": "Port mail",
"host": "Hôte du serveur mail",
"port": "Port du serveur mail",
"driver": "Pilote de courrier",
"password": "Mot de passe mail",
"password": "Mot de passe du serveur mail",
"secret": "Secret",
"mailgun_secret": "Mailgun Secret",
"mailgun_domain": "Domaine",
"mailgun_endpoint": "Mailgun Point Final",
"ses_secret": "SES Secret",
"ses_key": "SES clé",
"from_name": "Nom de messagerie",
"from_mail": "De ladresse mail",
"from_name": "Nom de l'email d'envoi",
"from_mail": "Adresse email d'envoi",
"username": "Mail Nom d'utilisateur",
"mail_config": "Configuration du courrier",
"encryption": "Chiffrement du courrier",
@ -581,9 +582,9 @@
"pdf_layout": "Mise en page PDF"
},
"company_info": {
"company_info": "Information dentreprise",
"company_info": "Information d'entreprise",
"company_name": "Nom de la compagnie",
"company_logo": "Logo dentreprise",
"company_logo": "Logo d'entreprise",
"section_description": "Informations sur votre entreprise qui figureront sur les factures, estimations et autres documents créés par Crater.",
"phone": "Téléphone",
"country": "Pays",
@ -774,7 +775,7 @@
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2019",
"copyright_crater": "Copyright @ Crater - 2020",
"super_simple_invoicing": "Super Simple Facturation",
"for_freelancer": "pour les pigistes et",
"small_businesses": "Petites entreprises ",
@ -787,6 +788,8 @@
"required": "Champ requis",
"email_incorrect": "Adresse Email incorrecte.",
"email_does_not_exist": "L'utilisateur avec un email donné n'existe pas",
"item_unit_already_taken": "L'unité d'article a déjà été prise",
"payment_mode_already_taken": "Le mode de paiement a déjà été pris",
"send_reset_link": "Envoyer le lien de réinitialisation",
"not_yet": "Pas encore? Envoyer à nouveau",
"password_min_length": "Le mot de passe doit contenir {nombre} caractères",

View File

@ -3,6 +3,9 @@ import VueI18n from 'vue-i18n'
import en from './en.json'
import fr from './fr.json'
import es from './es.json'
import ar from './ar.json'
import de from './de.json'
import pt_BR from './pt-br.json'
Vue.use(VueI18n)
@ -11,7 +14,10 @@ const i18n = new VueI18n({
messages: {
en,
fr,
es
es,
ar,
de,
pt_BR
}
})

View File

@ -0,0 +1,881 @@
{
"navigation": {
"dashboard": "Painel",
"customers": "Clientes",
"items": "Itens",
"invoices": "Faturas",
"expenses": "Despesas",
"estimates": "Orçamentos",
"payments": "Pagamentos",
"reports": "Relatórios",
"settings": "Configurações",
"logout": "Encerrar sessão"
},
"general": {
"view_pdf": "Ver PDF",
"download_pdf": "Baixar PDF",
"save": "Salvar",
"cancel": "Cancelar",
"update": "Atualizar",
"download": "Baixar",
"from_date": "A partir da Data",
"to_date": "Até a Data",
"from": "De",
"to": "Para",
"go_back": "Voltar",
"back_to_login": "Voltar ao Login",
"home": "Home",
"filter": "Filtrar",
"delete": "Excluir",
"edit": "Editar",
"view": "Ver",
"add_new_item": "Adicionar novo item",
"clear_all": "Limpar tudo",
"showing": "Mostrando",
"of": "de",
"actions": "Ações",
"subtotal": "Total parcial",
"discount": "Desconto",
"fixed": "Fixado",
"percentage": "Porcentagem",
"tax": "Imposto",
"total_amount": "Quantidade Total",
"bill_to": "Cobrar a",
"ship_to": "Envie a",
"due": "Vencida",
"draft": "Rascunho",
"sent": "Enviado",
"all": "Todos",
"select_all": "Selecionar tudo",
"choose_file": "Escolha um arquivo.",
"choose_template": "Escolha um modelo",
"choose": "Escolher",
"remove": "Excluir",
"powered_by": "Distribuído por",
"bytefury": "Bytefury",
"select_a_status": "Selecione um status",
"select_a_tax": "Selecione um Imposto",
"search": "Buscar",
"are_you_sure": "Tem certeza?",
"list_is_empty": "Lista está vazia.",
"no_tax_found": "Imposto não encontrado!",
"four_zero_four": "404",
"you_got_lost": "Ops! Se perdeu!",
"go_home": "Ir para Home",
"setting_updated": "Configuração atualizada com sucesso",
"select_state": "Selecione Estado",
"select_country": "Selecionar pais",
"select_city": "Selecionar cidade",
"street_1": "Rua 1",
"street_2": "Rua # 2",
"action_failed": "Ação: Falhou"
},
"dashboard": {
"select_year": "Selecione Ano",
"cards": {
"due_amount": "Montante devido",
"customers": "Clientes",
"invoices": "Faturas",
"estimates": "Orçamentos"
},
"chart_info": {
"total_sales": "Vendas",
"total_receipts": "Receitas",
"total_expense": "Despesas",
"net_income": "Resultado líquido",
"year": "Selecione Ano"
},
"weekly_invoices": {
"title": "Faturas Semanais"
},
"monthly_chart": {
"title": "Vendas e Despesas"
},
"recent_invoices_card": {
"title": "Faturas vencidas",
"due_on": "vencido em",
"customer": "Cliente",
"amount_due": "Valor Devido",
"actions": "Ações",
"view_all": "Ver todos"
},
"recent_estimate_card": {
"title": "Orçamentos Recentes",
"date": "Data",
"customer": "Cliente",
"amount_due": "Valor Devido",
"actions": "Ações",
"view_all": "Ver todos"
}
},
"tax_types": {
"name": "Nome",
"description": "Descrição",
"percent": "Porcentagem",
"compound_tax": "Imposto compuesto"
},
"customers": {
"title": "Clientes",
"add_customer": "Adicionar cliente",
"contacts_list": "Lista de clientes",
"name": "Nome",
"display_name": "Nome de exibição",
"primary_contact_name": "Nome do contato principal",
"contact_name": "Nome de Contato",
"amount_due": "Valor Devido",
"email": "Email",
"address": "Endereço",
"phone": "Telefone",
"website": "Site",
"country": "Pais",
"state": "Estado",
"city": "Cidade",
"zip_code": "Código postal",
"added_on": "Adicionado",
"action": "Ação",
"password": "Senha",
"street_number": "Número",
"primary_currency": "Moeda principal",
"add_new_customer": "Adicionar novo cliente",
"save_customer": "Salvar cliente",
"update_customer": "Atualizar cliente",
"customer": "Cliente | Clientes",
"new_customer": "Novo cliente",
"edit_customer": "Editar cliente",
"basic_info": "Informação basica",
"billing_address": "Endereço de cobrança",
"shipping_address": "Endereço de entrega",
"copy_billing_address": "Cópia de faturamento",
"no_customers": "Ainda não há clientes!",
"no_customers_found": "Clientes não encontrados!",
"list_of_customers": "Esta seção conterá a lista de clientes.",
"primary_display_name": "Nome de exibição principal",
"select_currency": "Selecione o tipo de moeda",
"select_a_customer": "Selecione um cliente",
"type_or_click": "Digite ou clique para selecionar",
"confirm_delete": "Você não poderá recuperar este cliente | Você não poderá recuperar esses clientes",
"created_message": "Cliente criado com sucesso",
"updated_message": "Cliente atualizado com sucesso",
"deleted_message": "Cliente excluído com sucesso | Clientes excluídos com sucesso"
},
"items": {
"title": "Itens",
"items_list": "Lista de Itens",
"name": "Nome",
"unit": "Unidade",
"description": "Descrição",
"added_on": "Adicionado",
"price": "Preço",
"date_of_creation": "Data de criação",
"action": "Ação",
"add_item": "Adicionar item",
"save_item": "Salvar item",
"update_item": "Atualizar item",
"item": "Item | Itens",
"add_new_item": "Adicionar novo item",
"new_item": "Novo item",
"edit_item": "Editar item",
"no_items": "Ainda não existe itens",
"list_of_items": "Esta seção conterá a lista de itens.",
"select_a_unit": "Seleciona unidade",
"item_attached_message": "Não é possível excluir um item que já está em uso.",
"confirm_delete": "Você não poderá recuperar este item | Você não poderá recuperar esses itens",
"created_message": "Item criado com sucesso",
"updated_message": "Item atualizado com sucesso",
"deleted_message": "Item excluído com sucesso | Itens Excluídos com sucesso"
},
"estimates": {
"title": "Orçamentos",
"estimate": "Orçamento | Orçamentos",
"estimates_list": "Lista de orçamentos",
"days": "{dias} dias",
"months": "{meses} Mês",
"years": "{Anos} Ano",
"all": "Todos",
"paid": "Pago",
"unpaid": "Não pago",
"customer": "CLIENTE",
"ref_no": "NÚMERO DE REFERÊNCIA.",
"number": "NÚMERO",
"amount_due": "Valor Devido",
"partially_paid": "Pago parcialmente",
"total": "Total",
"discount": "Desconto",
"sub_total": "Subtotal",
"estimate_number": "Numero do Orçamento",
"ref_number": "Referência",
"contact": "Contato",
"add_item": "Adicionar Item",
"date": "Data",
"due_date": "Data de Vencimento",
"expiry_date": "Data de expiração",
"status": "Status",
"add_tax": "Adicionar Imposto",
"amount": "Montante",
"action": "Ação",
"notes": "Observações",
"tax": "Imposto",
"estimate_template": "Modelo de orçamento",
"convert_to_invoice": "Converter em fatura",
"mark_as_sent": "Marcar como enviado",
"send_estimate": "Enviar orçamento",
"record_payment": "Registro de pago",
"add_estimate": "Adicionar orçamento",
"save_estimate": "Salvar Orçamento",
"confirm_conversion": "Deseja converter este orçamento em uma fatura?",
"conversion_message": "Converção realizada com sucesso",
"confirm_send_estimate": "Este orçamento será enviado por email ao cliente",
"confirm_mark_as_sent": "Este orçamento será marcado como enviado",
"confirm_mark_as_accepted": "Este orçamento será marcado como Aceito",
"confirm_mark_as_rejected": "Este orçamento será marcado como Rejeitado",
"no_matching_estimates": "Não há orçamentos correspondentes!",
"mark_as_sent_successfully": "Orçamento como marcado como enviado com sucesso",
"send_estimate_successfully": "Orçamento enviado com sucesso",
"errors": {
"required": "Campo obrigatório"
},
"accepted": "Aceito",
"sent": "Enviado",
"draft": "Rascunho",
"declined": "Rejeitado",
"new_estimate": "Novo orçamento",
"add_new_estimate": "Adicionar novo orçamento",
"update_Estimate": "Atualizar orçamento",
"edit_estimate": "Editar orçamento",
"items": "artículos",
"Estimate": "Orçamento | Orçamentos",
"add_new_tax": "Adicionar novo imposto",
"no_estimates": "Ainda não há orcamentos",
"list_of_estimates": "Esta seção contém a lista de orçamentos.",
"mark_as_rejected": "Marcar como rejeitado",
"mark_as_accepted": "Marcar como aceito",
"marked_as_accepted_message": "Orçamento marcado como aceito",
"marked_as_rejected_message": "Orçamento marcado como rejeitado",
"confirm_delete": "Não poderá recuperar este orçamento | Não poderá recuperar estes orçamentos",
"created_message": "Orçamento criado com sucesso",
"updated_message": "Orçamento atualizado com sucesso",
"deleted_message": "Orçamento excluído com sucesso | Orçamentos excluídos com sucesso",
"user_email_does_not_exist": "Email de usuário não existe",
"something_went_wrong": "Algo deu errado",
"item": {
"title": "Titulo do item",
"description": "Descrição",
"quantity": "Quantidade",
"price": "Preço",
"discount": "Desconto",
"total": "Total",
"total_discount": "Desconto total",
"sub_total": "Subtotal",
"tax": "Imposto",
"amount": "Montante",
"select_an_item": "Escreva ou clique para selecionar um item",
"type_item_description": "Tipo Item Descrição (opcional)"
}
},
"invoices": {
"title": "Faturas",
"invoices_list": "Lista de faturas",
"days": "{dias} dias",
"months": "{meses} Mês",
"years": "{anos} Ano",
"all": "Todas",
"paid": "Paga",
"unpaid": "Não Paga",
"customer": "CLIENTE",
"paid_status": "STATUS PAGAMENTO",
"ref_no": "REFERÊNCIA",
"number": "NÚMERO",
"amount_due": "VALOR DEVIDO",
"partially_paid": "Parcialmente pago",
"total": "Total",
"discount": "Desconto",
"sub_total": "Subtotal",
"invoice": "Fatura | Faturas",
"invoice_number": "Número da fatura",
"ref_number": "Referência",
"contact": "Contato",
"add_item": "Adicionar um item",
"date": "Data",
"due_date": "Data de Vencimento",
"status": "Status",
"add_tax": "Adicionar imposto",
"amount": "Montante",
"action": "Ação",
"notes": "Observações",
"view": "Ver",
"send_invoice": "Enviar Fatura",
"invoice_template": "Modelo da Fatura",
"template": "Modelo",
"mark_as_sent": "Marcar como enviada",
"confirm_send_invoice": "Esta fatura será enviada por e-mail ao cliente",
"invoice_mark_as_sent": "Esta fatura será marcada como enviada",
"confirm_send": "Esta fatura será enviada por e-mail ao cliente",
"invoice_date": "Data da Fatura",
"record_payment": "Gravar Pagamento",
"add_new_invoice": "Adicionar Nova Fatura",
"update_expense": "Atualizar Despesa",
"edit_invoice": "Editar Fatura",
"new_invoice": "Nova Fatura",
"save_invoice": "Salvar Fatura",
"update_invoice": "Atualizar Fatura",
"add_new_tax": "Adicionar novo Imposto",
"no_invoices": "Ainda não há faturas!",
"list_of_invoices": "Esta seção conterá a lista de faturas.",
"select_invoice": "Selecionar Fatura",
"no_matching_invoices": "Não há faturas correspondentes!",
"mark_as_sent_successfully": "Fatura marcada como enviada com sucesso",
"send_invoice_successfully": "Fatura enviada com sucesso",
"item": {
"title": "Titulo do Item",
"description": "Descrição",
"quantity": "Quantidade",
"price": "Preço",
"discount": "Desconto",
"total": "Total",
"total_discount": "Desconto Total",
"sub_total": "SubTotal",
"tax": "Imposto",
"amount": "Montante",
"select_an_item": "Digite ou clique para selecionar um item",
"type_item_description": "Tipo Descrição do item (opcional)"
},
"payment_attached_message": "Uma das faturas selecionadas já possui um pagamento anexado. Certifique-se de excluir os pagamentos anexados primeiro, a fim de prosseguir com a remoção",
"confirm_delete": "Você não poderá recuperar esta fatura | Você não poderá recuperar essas faturas",
"created_message": "Fatura criada com sucesso",
"updated_message": "Fatura atualizada com sucesso",
"deleted_message": "Fatura excluída com sucesso | Faturas excluídas com sucesso",
"marked_as_sent_message": "Fatura marcada como enviada com sucesso",
"user_email_does_not_exist": "O email do usuário não existe",
"something_went_wrong": "Algo deu errado",
"invalid_due_amount_message": "O valor total da fatura não pode ser menor que o valor total pago para esta fatura. Atualize a fatura ou exclua os pagamentos associados para continuar."
},
"credit_notes": {
"title": "Notas de credito",
"credit_notes_list": "Lista Notas de credito",
"credit_notes": "Notas de credito",
"contact": "Contato",
"date": "Data",
"amount": "Montante",
"action": "Ação",
"credit_number": "Número de crédito",
"notes": "Notes",
"confirm_delete": "Deseja excluir esta nota de crédito?",
"item": {
"title": "Título do Item",
"description": "Descrição",
"quantity": "Quantidade",
"price": "Preço",
"discount": "Desconto",
"total": "Total",
"total_discount": "Desconto Total",
"sub_total": "SubTotal",
"tax": "Imposto"
}
},
"payments": {
"title": "Pagamentos",
"payments_list": "Lista de Pagamentos",
"record_payment": "Gravar Pagamento",
"customer": "Cliente",
"date": "Data",
"amount": "Montante",
"action": "Ação",
"payment_number": "Número do Pagamento",
"payment_mode": "Forma de Pagamento",
"invoice": "Fatura",
"note": "Observação",
"add_payment": "Adicionar Pagamento",
"new_payment": "Novo Pagamento",
"edit_payment": "Editar Pagamento",
"view_payment": "Ver Pagamento",
"add_new_payment": "Adicionar novo Pagamento",
"save_payment": "Salvar Pagamento",
"update_payment": "Atualizar Pagamento",
"payment": "Pagamento | Pagamentos",
"no_payments": "Ainda sem pagamentos!",
"no_matching_payments": "Não há pagamentos correspondentes!",
"list_of_payments": "Esta seção conterá a lista de pagamentos.",
"select_payment_mode": "Selecione a forma de pagamento",
"confirm_delete": "Você não poderá recuperar este Pagamento | Você não poderá recuperar esses Pagamentos",
"created_message": "Pagamento criado com sucesso",
"updated_message": "Pagamento atualizado com sucesso",
"deleted_message": "Pagamento excluído com sucesso | Pagamentos excluídos com sucesso",
"invalid_amount_message": "O valor do pagamento é inválido"
},
"expenses": {
"title": "Despesas",
"expenses_list": "Lista de Despesas",
"expense_title": "Título",
"contact": "Contato",
"category": "Categoria",
"from_date": "A partir da Data",
"to_date": "Até a Data",
"expense_date": "Data",
"description": "Descrição",
"receipt": "Receita",
"amount": "Montante",
"action": "Ação",
"note": "Observação",
"category_id": "Categoria",
"date": "Data da Despesa",
"add_expense": "Adicionar Despesa",
"add_new_expense": "Adicionar Nova Despesa",
"save_expense": "Salvar Despesa",
"update_expense": "Atualizar Despesa",
"download_receipt": "Baixar Receita",
"edit_expense": "Editar Despesa",
"new_expense": "Nova Despesa",
"expense": "Despesa | Despesas",
"no_expenses": "Ainda sem Despesas!",
"list_of_expenses": "Esta seção conterá a lista de despesas.",
"confirm_delete": "Você não poderá recuperar esta despesa | Você não poderá recuperar essas despesas",
"created_message": "Despesa criada com sucesso",
"updated_message": "Despesa atualizada com sucesso",
"deleted_message": "Despesas excluídas com sucesso | Despesas excluídas com sucesso",
"categories": {
"categories_list": "Lista de Categorias",
"title": "Título",
"name": "Nome",
"description": "Descrição",
"amount": "Montante",
"actions": "Ações",
"add_category": "Adicionar Categoria",
"new_category": "Nova Categoria",
"category": "Categoria | Categorias",
"select_a_category": "Selecionar uma Categoria"
}
},
"login": {
"email": "Email",
"password": "Senha",
"forgot_password": "Esqueceu a senha?",
"or_signIn_with": "ou Entre com",
"login": "Entrar",
"register": "Registre-se",
"reset_password": "Resetar Senha",
"password_reset_successfully": "Senha redefinida com sucesso",
"enter_email": "Digite email",
"enter_password": "Digite a senha",
"retype_password": "Confirme a Senha",
"login_placeholder": "mail@exemplo.com"
},
"reports": {
"title": "Relatório",
"from_date": "A partir da Data",
"to_date": "Até a Data",
"status": "Status",
"paid": "Pago",
"unpaid": "Não Pago",
"download_pdf": "Baixar PDF",
"view_pdf": "Ver PDF",
"update_report": "Atualizar Relatório",
"report": "Relatório | Relatórios",
"profit_loss": {
"profit_loss": "Perda de lucro",
"to_date": "Até a Data",
"from_date": "A partir da Data",
"date_range": "Selecionar período"
},
"sales": {
"sales": "Vendas",
"date_range": "Selecionar período",
"to_date": "Até a Data",
"from_date": "A partir da Data",
"report_type": "Tipo de Relatório"
},
"taxes": {
"taxes": "Impostos",
"to_date": "Até a Data",
"from_date": "A partir da Data",
"date_range": "Selecionar período"
},
"errors": {
"required": "Campo obrigatório"
},
"invoices": {
"invoice": "Fatura",
"invoice_date": "Data da Fatura",
"due_date": "Data de Vencimento",
"amount": "Montante",
"contact_name": "Nome de Contato",
"status": "Status"
},
"estimates": {
"estimate": "Orçamento",
"estimate_date": "Data do Orçamento",
"due_date": "Data de Vencimento",
"estimate_number": "Número do Orçamento",
"ref_number": "Referência",
"amount": "Montante",
"contact_name": "Nome de Contato",
"status": "Status"
},
"expenses": {
"expenses": "Despesas",
"category": "Categoria",
"date": "Data",
"amount": "Montante",
"to_date": "Até a Data",
"from_date": "A partir da Data",
"date_range": "Selecionar período"
}
},
"settings": {
"menu_title": {
"account_settings": "Configurações da conta",
"company_information": "Informações da Empresa",
"customization": "Personalizar",
"preferences": "Preferências",
"notifications": "Notificações",
"tax_types": "Tipos de Impostos",
"expense_category": "Categorias de Despesas",
"update_app": "Atualizar Aplicativo"
},
"title": "Configurações",
"setting": "Configuração | Configurações",
"general": "Geral",
"language": "Idioma",
"primary_currency": "Moéda Principal",
"timezone": "Fuso horário",
"date_format": "Formato de data",
"currencies": {
"title": "Moedas",
"currency": "Moeda | Moedas",
"currencies_list": "Moedas",
"select_currency": "Selecione uma Moeda",
"name": "Nome",
"code": "Código",
"symbol": "Símbolo",
"precision": "Precisão",
"thousand_separator": "Separador de Milhar",
"decimal_separator": "Separador Decimal",
"position": "Posição",
"position_of_symbol": "Posição do Símbolo",
"right": "Direita",
"left": "Esquerda",
"action": "Ação",
"add_currency": "Adicionar Moeda"
},
"mail": {
"host": "Host de Email",
"port": "Porta de Email",
"driver": "Mail Driver",
"secret": "Segredo",
"mailgun_secret": "Mailgun Segredo",
"mailgun_domain": "Domínio",
"mailgun_endpoint": "Mailgun Endpoint",
"ses_secret": "SES Segredo",
"ses_key": "SES Chave",
"password": "Senha do Email",
"username": "Nome de Usuário do Email",
"mail_config": "Configuração de Email",
"from_name": "Do Nome de Email",
"from_mail": "Do Endereço de Email",
"encryption": "Criptografia de Email",
"mail_config_desc": "Abaixo está o formulário para configurar o driver de email para enviar emails do aplicativo. Você também pode configurar provedores de terceiros como Sendgrid, SES etc."
},
"pdf": {
"title": "Configurações de PDF",
"footer_text": "Texto do Rodapé",
"pdf_layout": "Layout de PDF"
},
"company_info": {
"company_info": "Informação da Empresa",
"company_name": "Nome da Empresa",
"company_logo": "Logotipo da Empresa",
"section_description": "Informações sobre sua empresa que serão exibidas em Faturas, Orçamentos e outros documentos criados pela Crater.",
"phone": "Telefone",
"country": "Pais",
"state": "Estado",
"city": "Cidade",
"address": "Endereço",
"zip": "CEP",
"save": "Salvar",
"updated_message": "Informações da Empresa atualizadas com sucesso"
},
"customization": {
"customization": "Personalizar",
"save": "Salvar",
"addresses": {
"title": "Endereço",
"section_description": "Você pode definir o endereço de cobrança do cliente e o formato do endereço de entrega do cliente (exibido apenas em PDF).",
"customer_billing_address": "Endereço de Cobrança do Cliente",
"customer_shipping_address": "Endereço de Entrega do Cliente",
"company_address": "Endereço da Empresa",
"insert_fields": "Inserir Campos",
"contact": "Contato",
"address": "Endereço",
"display_name": "Nome em Exibição",
"primary_contact_name": "Nome do Contato Principal",
"email": "Email",
"website": "Website",
"name": "Nome",
"country": "Pais",
"state": "Estado",
"city": "Cidade",
"company_name": "Nome da Empresa",
"address_street_1": "Endereço Rua 1",
"address_street_2": "Endereço Rua 2",
"phone": "Telefone",
"zip_code": "CEP",
"address_setting_updated": "Configuração de Endereço Atualizada com Sucesso"
},
"updated_message": "Informações da Empresa atualizadas com sucesso",
"invoices": {
"title": "Faturas",
"notes": "Notas",
"invoice_prefix": "Fatura Prefixo",
"invoice_settings": "Configrações da Fatura",
"autogenerate_invoice_number": "Gerar automaticamente o número da Fatura",
"invoice_setting_description": "Desative isso, se você não deseja gerar automaticamente números da Fatura sempre que criar uma nova.",
"enter_invoice_prefix": "Digite o prefixo da Fatura",
"terms_and_conditions": "Termos e Condições",
"invoice_setting_updated": "Configuração da Fatura atualizada com sucesso"
},
"estimates": {
"title": "Orçamentos",
"estimate_prefix": "Orçamento Prefixo",
"estimate_settings": "Configurações do Orçamento",
"autogenerate_estimate_number": "Gerar automaticamente o número do Orçamento",
"estimate_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Orçamento sempre que criar um novo.",
"enter_estimate_prefix": "Digite o prefixo do Orçamento",
"estimate_setting_updated": "Configuração do Orçamento atualizada com sucesso"
},
"payments": {
"title": "Pagamentos",
"payment_prefix": "Pagamento Prefixo",
"payment_settings": "Configurações de Pagamento",
"autogenerate_payment_number": "Gerar automaticamente número do Pagamento",
"payment_setting_description": "Desative isso, se você não deseja gerar automaticamente números do Pagamento sempre que criar um novo.",
"enter_payment_prefix": "Digite o Prefixo do Pagamento",
"payment_setting_updated": "Configurações de Pagamento atualizada com sucesso"
}
},
"account_settings": {
"profile_picture": "Foto do Perfil",
"name": "Nome",
"email": "Email",
"password": "Senha",
"confirm_password": "Confirmar Senha",
"account_settings": "Configurações da conta",
"save": "Salvar",
"section_description": "Você pode atualizar seu nome, email e senha usando o formulário abaixo.",
"updated_message": "Configurações da conta atualizadas com sucesso"
},
"user_profile": {
"name": "Nome",
"email": "Email",
"password": "Password",
"confirm_password": "Confirmar Senha"
},
"notification": {
"title": "Notificação",
"email": "Enviar Notificações para",
"description": "Quais notificações por email você gostaria de receber quando algo mudar?",
"invoice_viewed": "Fatura Visualizada",
"invoice_viewed_desc": "Quando o seu cliente visualiza uma Fatura enviada pelo painel do Crater.",
"estimate_viewed": "Orçamento Visualizado",
"estimate_viewed_desc": "Quando o seu cliente visualiza um Orçamento enviada pelo painel do Crater.",
"save": "Salvar",
"email_save_message": "E-mail salvo com sucesso",
"please_enter_email": "Por favor digite um E-mail"
},
"tax_types": {
"title": "Tipos de Impostos",
"add_tax": "Adicionar Imposto",
"description": "Você pode adicionar ou remover impostos conforme desejar. O Crater suporta impostos sobre itens individuais e também na Fatura.",
"add_new_tax": "Adicionar Novo Imposto",
"tax_settings": "Configurações de Impostos",
"tax_per_item": "Imposto por Item",
"tax_name": "Nome do Imposto",
"compound_tax": "Imposto Composto",
"percent": "Porcentagem",
"action": "Ação",
"tax_setting_description": "Habilite isso se desejar adicionar Impostos a itens da Fatura Idividualmente. Por padrão, os impostos são adicionados diretamente à Fatura.",
"created_message": "Tipo de Imposto criado com sucesso",
"updated_message": "Tipo de Imposto Atualizado com sucesso",
"deleted_message": "Tipo de Imposto Deletado com sucesso",
"confirm_delete": "Você não poderá recuperar este tipo de Imposto",
"already_in_use": "O Imposto já está em uso"
},
"expense_category": {
"title": "Categoria de Despesa",
"action": "Ação",
"description": "As Categorias são necessárias para adicionar entradas de Despesas. Você pode adicionar ou remover essas Categorias de acordo com sua preferência.",
"add_new_category": "Adicionar Nova Categoria",
"category_name": "Nome da Categoria",
"category_description": "Descrição",
"created_message": "Categoria de Despesa criada com sucesso",
"deleted_message": "Categoria de Despesa excluída com sucesso",
"updated_message": "Categoria de Despesa atualizada com sucesso",
"confirm_delete": "Você não poderá recuperar esta Categoria de Despesa",
"already_in_use": "A categoria já está em uso"
},
"preferences": {
"currency": "Moeda",
"language": "Idioma",
"time_zone": "Fuso Horário",
"fiscal_year": "Ano Financeiro",
"date_format": "Formato da Data",
"discount_setting": "Configuração de Desconto",
"discount_per_item": "Desconto por Item ",
"discount_setting_description": "Habilite isso se desejar adicionar desconto a itens de Fatura individualmente. Por padrão, o desconto é adicionado diretamente à Fatura.",
"save": "Salvar",
"preference": "Preferência | Preferências",
"general_settings": "Preferências padrão para o sistema.",
"updated_message": "Preferências atualizadas com sucesso",
"select_language": "Selecione um Idioma",
"select_time_zone": "Selecione um fuso horário",
"select_date_formate": "Selecione um formato de data",
"select_financial_year": "Selecione o ano financeiro"
},
"update_app": {
"title": "Atualizar Aplicativo",
"description": "Você pode atualizar facilmente o Crater, verifique se hà novas atualizações, clicando no botão abaixo",
"check_update": "Verifique se há atualizações",
"avail_update": "Nova atualização disponível",
"next_version": "Próxima versão",
"update": "Atualizar agora",
"update_progress": "Atualização em progresso...",
"progress_text": "Levará apenas alguns minutos. Não atualize a tela ou feche a janela antes que a atualização seja concluída",
"update_success": "O aplicativo foi atualizado! Aguarde enquanto a janela do navegador é recarregada automaticamente.",
"latest_message": "Nenhuma atualização disponível! Você está na versão mais recente.",
"current_version": "Versão Atual"
}
},
"wizard": {
"account_info": "Informação da conta",
"account_info_desc": "Os detalhes abaixo serão usados para criar a conta principal do administrador. Além disso, você pode alterar os detalhes a qualquer momento após o login.",
"name": "Nome",
"email": "Email",
"password": "Senha",
"confirm_password": "Confirmar Senha",
"save_cont": "Salvar e Continuar",
"company_info": "Informação da Empresa",
"company_info_desc": "Esta informação será exibida nas Faturas. Observe que você pode editar isso mais tarde na página de configurações.",
"company_name": "Nome da Empresa",
"company_logo": "Logotipo da Empresa",
"logo_preview": "Previsualizar Logotipo",
"preferences": "Preferências",
"preferences_desc": "Preferências padrão para o sistema.",
"country": "Pais",
"state": "Estado",
"city": "Cidade",
"address": "Endereço",
"street": "Rua 1 | Rua 2",
"phone": "Telefone",
"zip_code": "CEP",
"go_back": "Voltar",
"currency": "Moeda",
"language": "Idioma",
"time_zone": "Fuso Horário",
"fiscal_year": "Ano Financeiro",
"date_format": "Formato de Data",
"from_address": "Do Endereço",
"username": "Nome de Usuário",
"next": "Próximo",
"continue": "Continuar",
"skip": "Pular",
"database": {
"database": "URL do Site e Base de Dados",
"connection": "Conexão da Base de Dados",
"host": "Host da Base de Dados",
"port": "Porta da Base de Dados",
"password": "Senha da Base de Dados",
"app_url": "URL do Aplicativo",
"username": "Usuário da Base de Dados",
"db_name": "Nome da Base de Dados",
"desc": "Crie um Banco de Dados no seu servidor e defina as credenciais usando o formulário abaixo."
},
"permissions": {
"permissions": "Permissões",
"permission_confirm_title": "Você tem certeza que quer continuar?",
"permission_confirm_desc": "Falha na verificação de permissão da pasta",
"permission_desc": "Abaixo está a lista de permissões de pasta que são necessárias para que o aplicativo funcione. Se a verificação da permissão falhar, atualize as permissões da pasta."
},
"mail": {
"host": "Host do email",
"port": "Porta do email",
"driver": "Driver do email",
"secret": "Segredo",
"mailgun_secret": "Segredo do Mailgun",
"mailgun_domain": "Domínio",
"mailgun_endpoint": "Endpoint do Mailgun",
"ses_secret": "Segredo do SES",
"ses_key": "Chave SES",
"password": "Senha do email",
"username": "Nome do Usuário do email",
"mail_config": "Configuração de email",
"from_name": "Nome do email",
"from_mail": "Endereço de email",
"encryption": "Criptografia de email",
"mail_config_desc": "Abaixo está o formulário para configurar o driver de email que será usado para enviar emails do aplicativo. Você também pode configurar provedores de terceiros como Sendgrid, SES etc."
},
"req": {
"system_req": "Requisitos de Sistema",
"php_req_version": "PHP (versão {version} obrigatória)",
"check_req": "Verificar Requisitos",
"system_req_desc": "O Crater tem alguns requisitos de servidor. Verifique se o seu servidor possui a versão do PHP necessária e todas as extensões mencionadas abaixo."
},
"errors": {
"migrate_failed": "Falha na migração",
"database_variables_save_error": "Não é possível gravar a configuração no arquivo .env. Por favor, verifique suas permissões de arquivo",
"mail_variables_save_error": "A configuração do email falhou.",
"connection_failed": "Falha na conexão com o banco de dados",
"database_should_be_empty": "O banco de dados deve estar vazio"
},
"success": {
"mail_variables_save_successfully": "Email configurado com sucesso",
"database_variables_save_successfully": "Banco de dados configurado com sucesso."
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2020",
"super_simple_invoicing": "Faturamento super simples",
"for_freelancer": "Para Freelancers &",
"small_businesses": "Pequenos Negócios ",
"crater_help": "Crater ajuda a rastrear despesas, registrar pagamentos e gerar belas",
"invoices_and_estimates": "Faturas e Orçamentos com capacidade de escolher vários modelos."
},
"validation": {
"invalid_url": "url inválidas (ex: http://www.crater.com)",
"required": "Campo obrigatório",
"email_incorrect": "E-mail incorreto",
"email_already_taken": "O email já foi recebido.",
"email_does_not_exist": "O usuário com determinado email não existe",
"send_reset_link": "Enviar link de redefinição",
"not_yet": "Ainda não? Envie novamente",
"password_min_length": "A senha deve conter {count} caracteres",
"name_min_length": "O nome deve ter pelo menos {count} letras.",
"enter_valid_tax_rate": "Insira uma taxa de imposto válida",
"numbers_only": "Apenas Números.",
"characters_only": "Apenas Caracteres.",
"password_incorrect": "As senhas devem ser idênticas",
"password_length": "A senha deve ter {count} caracteres.",
"qty_must_greater_than_zero": "A quantidade deve ser maior que zero.",
"price_greater_than_zero": "O preço deve ser maior que zero.",
"payment_greater_than_zero": "O pagamento deve ser maior que zero.",
"payment_greater_than_due_amount": "O pagamento inserido é mais do que o valor devido desta fatura.",
"quantity_maxlength": "A quantidade não deve exceder 20 dígitos.",
"price_maxlength": "O preço não deve ser superior a 20 dígitos.",
"price_minvalue": "O preço deve ser maior que 0.",
"amount_maxlength": "Montante não deve ser superior a 20 dígitos.",
"amount_minvalue": "Montante deve ser maior que zero",
"description_maxlength": "A descrição não deve ter mais que 255 caracteres.",
"maximum_options_error": "Máximo de {max} opções selecionadas. Primeiro remova uma opção selecionada para selecionar outra.",
"notes_maxlength": "As anotações não devem ter mais que 255 caracteres.",
"address_maxlength": "O endereço não deve ter mais que 255 caracteres.",
"ref_number_maxlength": "O número de referência não deve ter mais que 255 caracteres.",
"prefix_maxlength": "O prefixo não deve ter mais que 5 caracteres."
}
}

View File

@ -46,6 +46,7 @@ import InvoiceView from './views/invoices/View.vue'
// Payments
import PaymentsIndex from './views/payments/Index.vue'
import PaymentCreate from './views/payments/Create.vue'
import PaymentView from './views/payments/View.vue'
// Estimates
import EstimateIndex from './views/estimates/Index.vue'
@ -66,6 +67,7 @@ import ReportLayout from './views/reports/layout/Index.vue'
// Settings
import SettingsLayout from './views/settings/layout/Index.vue'
import CompanyInfo from './views/settings/CompanyInfo.vue'
import Customization from './views/settings/Customization.vue'
import Notifications from './views/settings/Notifications.vue'
import Preferences from './views/settings/Preferences.vue'
import UserProfile from './views/settings/UserProfile.vue'
@ -258,6 +260,11 @@ const routes = [
name: 'payments.edit',
component: PaymentCreate
},
{
path: 'payments/:id/view',
name: 'payments.view',
component: PaymentView
},
// Expenses
{
@ -309,6 +316,11 @@ const routes = [
name: 'company.info',
component: CompanyInfo
},
{
path: 'customization',
name: 'customization',
component: Customization
},
{
path: 'user-profile',
name: 'user.profile',

View File

@ -4,18 +4,23 @@ import * as userTypes from './modules/user/mutation-types'
import * as companyTypes from './modules/company/mutation-types'
import * as preferencesTypes from './modules/settings/preferences/mutation-types'
import * as taxTypeTypes from './modules/tax-type/mutation-types'
import * as itemTypes from './modules/item/mutation-types'
import * as paymentModes from './modules/payment/mutation-types'
export default {
bootstrap ({ commit, dispatch, state }) {
return new Promise((resolve, reject) => {
window.axios.get('/api/bootstrap').then((response) => {
commit('company/' + companyTypes.BOOTSTRAP_COMPANIES, response.data.companies)
commit('company/' + companyTypes.SET_SELECTED_COMPANY, response.data.company)
commit('currency/' + currencyTypes.BOOTSTRAP_CURRENCIES, response.data)
commit('currency/' + currencyTypes.SET_DEFAULT_CURRENCY, response.data)
commit('user/' + userTypes.BOOTSTRAP_CURRENT_USER, response.data.user)
commit('company/' + companyTypes.BOOTSTRAP_COMPANIES, response.data.companies)
commit('taxType/' + taxTypeTypes.BOOTSTRAP_TAX_TYPES, response.data.taxTypes)
commit('preferences/' + preferencesTypes.SET_MOMENT_DATE_FORMAT, response.data.moment_date_format)
commit('preferences/' + preferencesTypes.SET_LANGUAGE_FORMAT, response.data.default_language)
commit('item/' + itemTypes.SET_ITEM_UNITS, response.data.units)
commit('payment/' + paymentModes.SET_PAYMENT_MODES, response.data.paymentMethods)
commit(types.UPDATE_APP_LOADING_STATUS, true)
resolve(response)
}).catch((err) => {

View File

@ -2,7 +2,7 @@ import * as types from './mutation-types'
export const fetchCategories = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.get(`/api/categories/`).then((response) => {
window.axios.get(`/api/categories`).then((response) => {
commit(types.SET_CATEGORIES, response.data)
resolve(response)
}).catch((err) => {

View File

@ -1,7 +1,5 @@
import * as types from './mutation-types'
import Ls from '@/services/ls'
export const setSelectedCompany = ({ commit, dispatch, state }, data) => {
Ls.set('selectedCompany', data.id)
commit(types.SET_SELECTED_COMPANY, data)
}

View File

@ -1,4 +1,5 @@
import * as types from './mutation-types'
import Ls from '@/services/ls'
export default {
[types.BOOTSTRAP_COMPANIES] (state, companies) {
@ -6,6 +7,7 @@ export default {
state.selectedCompany = companies[0]
},
[types.SET_SELECTED_COMPANY] (state, company) {
Ls.set('selectedCompany', company.id)
state.selectedCompany = company
}
}

View File

@ -13,13 +13,13 @@ export const loadData = ({ commit, dispatch, state }, params) => {
})
}
export const getChart = ({ commit, dispatch, state }) => {
return new Promise((resolve, reject) => {
window.axios.get(`/api/dashboard/expense/chart`).then((response) => {
commit(types.SET_INITIAL_DATA, response.data)
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
// export const getChart = ({ commit, dispatch, state }) => {
// return new Promise((resolve, reject) => {
// window.axios.get(`/api/dashboard/expense/chart`).then((response) => {
// commit(types.SET_INITIAL_DATA, response.data)
// resolve(response)
// }).catch((err) => {
// reject(err)
// })
// })
// }

View File

@ -135,6 +135,16 @@ export const markAsSent = ({ commit, dispatch, state }, data) => {
})
}
export const cloneInvoice = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.post(`/api/invoices/clone`, data).then((response) => {
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
export const searchInvoice = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.get(`/api/invoices?${data}`).then((response) => {

View File

@ -26,7 +26,6 @@ export const addItem = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.post('/api/items', data).then((response) => {
commit(types.ADD_ITEM, response.data)
resolve(response)
}).catch((err) => {
reject(err)
@ -90,3 +89,59 @@ export const selectItem = ({ commit, dispatch, state }, data) => {
commit(types.SET_SELECT_ALL_STATE, false)
}
}
export const addItemUnit = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.post(`/api/units`, data).then((response) => {
commit(types.ADD_ITEM_UNIT, response.data)
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
export const updateItemUnit = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.put(`/api/units/${data.id}`, data).then((response) => {
commit(types.UPDATE_ITEM_UNIT, response.data)
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
export const fetchItemUnits = ({ commit, dispatch, state }) => {
return new Promise((resolve, reject) => {
window.axios.get(`/api/units`).then((response) => {
commit(types.SET_ITEM_UNITS, response.data.units)
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
export const fatchItemUnit = ({ commit, dispatch, state }, id) => {
return new Promise((resolve, reject) => {
window.axios.get(`/api/units/${id}`).then((response) => {
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
export const deleteItemUnit = ({ commit, dispatch, state }, id) => {
return new Promise((resolve, reject) => {
window.axios.delete(`/api/units/${id}`).then((response) => {
if (!response.data.error) {
commit(types.DELETE_ITEM_UNIT, id)
}
resolve(response)
}).catch((err) => {
reject(err)
})
})
}

View File

@ -2,3 +2,4 @@ export const items = (state) => state.items
export const selectAllField = (state) => state.selectAllField
export const selectedItems = (state) => state.selectedItems
export const totalItems = (state) => state.totalItems
export const itemUnits = (state) => state.itemUnits

View File

@ -6,7 +6,8 @@ const initialState = {
items: [],
totalItems: 0,
selectAllField: false,
selectedItems: []
selectedItems: [],
itemUnits: []
}
export default {

View File

@ -6,3 +6,7 @@ export const DELETE_MULTIPLE_ITEMS = 'DELETE_MULTIPLE_ITEMS'
export const SET_SELECTED_ITEMS = 'SET_SELECTED_ITEMS'
export const SET_TOTAL_ITEMS = 'SET_TOTAL_ITEMS'
export const SET_SELECT_ALL_STATE = 'SET_SELECT_ALL_STATE'
export const ADD_ITEM_UNIT = 'ADD_ITEM_UNIT'
export const SET_ITEM_UNITS = 'SET_ITEM_UNITS'
export const UPDATE_ITEM_UNIT = 'UPDATE_ITEM_UNIT'
export const DELETE_ITEM_UNIT = 'DELETE_ITEM_UNIT'

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