Compare commits

...

166 Commits
1.0.0 ... 2.1.0

Author SHA1 Message Date
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
9424dc6c27 refactor initial data loading in dashboard 2019-12-09 19:27:21 +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
f4a4c05b61 Merge branch 'build-201' into 'master'
Build 201

See merge request mohit.panjvani/crater-web!120
2019-12-04 12:47:51 +00:00
24637bff4a add estimate & invoice item qty cast, build 201 2019-12-04 17:08:36 +05:30
887ad9a73d build version 201 2019-12-04 16:51:22 +05:30
339099bd34 remove qty from inoice & estimate migration change 2019-12-04 16:43:21 +05:30
9b9761aa5a refactor invoice & estimate migrations 2019-12-04 16:38:25 +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
00c917853c Merge branch 'build-201' into 'master'
Build 201

See merge request mohit.panjvani/crater-web!113
2019-12-04 08:15:42 +00:00
122c4f478f build version-201 2019-12-04 13:39:58 +05:30
edc0e115e4 fix database connection issue 2019-12-04 13:38:51 +05:30
b388e7a237 Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into build-201 2019-12-04 13:18:22 +05:30
6e3ed9b4f6 Merge branch 'connection-issue' into 'master'
get error message for connection failed

See merge request mohit.panjvani/crater-web!112
2019-12-04 07:45:53 +00:00
338dbb26a1 refactor database connection failed error message 2019-12-04 13:02:38 +05:30
f10e5e9d11 build 201 2019-12-04 12:39:57 +05:30
3a046b638c decrease update app timeout 2019-12-04 12:34:41 +05:30
36242c516a fix listener issue 2019-12-04 12:32:26 +05:30
14d71fedb3 Rename docker-compose.yml.example -> docker-compose.yaml.example 2019-12-04 14:54:28 +08:00
c8843eb544 get error message for connection failed 2019-12-04 12:22:23 +05:30
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
37f2b6dfc7 Merge branch 'build-201' into 'master'
add listener for version 201

See merge request mohit.panjvani/crater-web!107
2019-12-04 06:03:19 +00:00
c90c14312a add listener for version 201 2019-12-04 11:29:39 +05:30
b5b861bb36 Merge branch 'build-200' into 'master'
replace city & state object with their name

See merge request mohit.panjvani/crater-web!106
2019-12-04 05:36:55 +00:00
ab041743a2 remove state & city name from shipping address 2019-12-04 09:41:59 +05:30
9bcec9bd75 replace city & state object with their name 2019-12-04 09:37:22 +05:30
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
f4ca6d4b73 Merge branch 'build-200' into 'master'
fix customer select issue

See merge request mohit.panjvani/crater-web!100
2019-12-02 10:16:37 +00:00
66649590e5 fix customer select issue 2019-12-02 15:44:16 +05:30
1e8cc475ca Merge branch 'build-200' into 'master'
build version200

See merge request mohit.panjvani/crater-web!99
2019-12-02 08:45:52 +00:00
98d76a2f92 build version200 2019-12-02 14:07:56 +05:30
7b50148c43 Merge branch 'fix-issue' into 'master'
fix app_url and quantity validation issue

See merge request mohit.panjvani/crater-web!97
2019-12-02 08:22:59 +00:00
aef6da8b7b add utilities 2019-12-02 11:49:41 +05:30
0fb14afc08 fix app_url and quantity validation issue 2019-12-02 11:48:48 +05:30
dad71b04dd Merge branch 'dev' 2019-12-02 11:18:22 +05:30
80014b02b5 fix sql-mode issue 2019-12-01 11:22:28 +05:30
7c2a6700eb Merge branch 'master' 2019-11-28 19:54:14 +05:30
7e81013b15 Merge branch 'mysql-fix' into 'master'
fix groupby issue on mysql

See merge request mohit.panjvani/crater-web!90
2019-11-28 12:52:03 +00:00
f0107129fb fix groupby issue on mysql 2019-11-28 16:06:18 +05:30
04cce64859 Add transifex link to readme 2019-11-28 13:56:41 +05:30
3b7637f3cf Merge branch 'master' into dev 2019-11-27 12:11:49 +05:30
7333746948 Merge branch 'record-payment' into 'master'
fix record payment from view invoice

See merge request mohit.panjvani/crater-web!79
2019-11-27 06:13:46 +00:00
0fa6049298 Merge branch 'language-json' into 'master'
convert language JS into JSON file

See merge request mohit.panjvani/crater-web!84
2019-11-27 06:11:01 +00:00
64be6ce957 Merge branch 'version-200' into 'dev'
Version 200

See merge request mohit.panjvani/crater-web!85
2019-11-27 06:02:38 +00:00
0e075c03d8 Merge branch 'fix-bug' into 'master'
fix `name` of undefined issue

See merge request mohit.panjvani/crater-web!83
2019-11-26 12:27:58 +00:00
5de195b56b convert language js into JSON file 2019-11-26 17:09:26 +05:30
cd60f1b096 fix name of undefined issue 2019-11-25 22:58:28 +05:30
8058f9b022 fix update timeout listener error 2019-11-25 18:01:40 +05:30
a484506029 fix seeder issue 2019-11-25 15:44:01 +05:30
a69f99dc61 remove state and city files 2019-11-25 15:38:21 +05:30
c3583c98be add version to config 2019-11-25 14:16:02 +05:30
813e574425 fix route issue 2019-11-25 13:47:26 +05:30
ac431ca815 remove state & city stuff, Add listener version200 2019-11-25 13:46:57 +05:30
3158955d00 Merge branch 'master' of https://github.com/bytefury/crater 2019-11-23 19:31:17 +05:30
dbc5950294 fix record payment from view invoice 2019-11-23 19:30:49 +05:30
00a218fe87 build version110 2019-11-23 18:21:03 +05:30
4a92469465 Merge branch 'version-110' into 'master'
add currencies symbol in listener

See merge request mohit.panjvani/crater-web!76
2019-11-23 12:49:28 +00:00
cd67ebd487 fix customer validation issue 2019-11-23 18:01:46 +05:30
6853d0bb57 add currencies symbol in listener 2019-11-23 16:57:36 +05:30
9afc19268a build version 110 2019-11-23 15:28:01 +05:30
f6faf10d43 fix description line-endings 2019-11-23 15:21:39 +05:30
b061102c23 build version-110 2019-11-23 14:20:40 +05:30
e8b8cd9f04 Merge branch 'version-110' into 'master'
fix permission success issue

See merge request mohit.panjvani/crater-web!75
2019-11-23 08:39:49 +00:00
9f4b5e02e8 fix permission success issue 2019-11-23 14:08:01 +05:30
1c84c1f843 rename BaseDatePicker 2019-11-23 13:52:00 +05:30
23beb5cac7 Merge branch 'master' 2019-11-23 13:48:06 +05:30
2fb2f1fcc0 update comment 2019-11-23 13:47:42 +05:30
7c1529f890 build 110 2019-11-23 13:46:24 +05:30
8b54b48805 stop window from closing when update in progress 2019-11-23 13:43:29 +05:30
07601a7130 refactor update listener and reload browser window on update success 2019-11-23 13:15:58 +05:30
7fd1224502 Merge branch 'version-110' into 'master'
add confirm box for folder permission on installation

See merge request mohit.panjvani/crater-web!73
2019-11-23 07:16:00 +00:00
1d56bd9f36 fix permission confirm box title issue 2019-11-23 12:41:47 +05:30
a8783cc929 Merge branch 'master' 2019-11-23 12:39:37 +05:30
841ff06005 clean unused code 2019-11-23 12:39:21 +05:30
3a54167ec7 Merge branch 'currency-changes' into 'master'
Add currency symbol

See merge request mohit.panjvani/crater-web!74
2019-11-23 07:07:51 +00:00
bc18f9b198 add confirm box for folder permission on installation 2019-11-23 12:34:10 +05:30
6741f9849d fix multiselect disabled style 2019-11-23 12:33:33 +05:30
14c0f7f486 Add currency symbol 2019-11-23 12:31:30 +05:30
095f3c0b31 Merge branch 'master' of gitlab.com:mohit.panjvani/crater-web 2019-11-23 12:18:48 +05:30
f2ad8286d7 fix label class 2019-11-23 12:18:27 +05:30
18ad27d513 Merge branch 'customer' into 'master'
Fix customer email already exist validation when edit customer

See merge request mohit.panjvani/crater-web!71
2019-11-23 06:42:41 +00:00
06807275b9 fix item reports issue 2019-11-23 11:54:35 +05:30
2ad39bfbd6 Merge branch 'version-110' into 'master'
fix installation issue & add ver update listener

See merge request mohit.panjvani/crater-web!68
2019-11-23 06:15:49 +00:00
9f38947fe7 Merge branch 'user-avatar' into 'master'
User Avatar

See merge request mohit.panjvani/crater-web!67
2019-11-23 06:09:08 +00:00
81c1e78bed fix taxes issue 2019-11-22 16:07:31 +05:30
dd0817709b fix installation issue & add ver update listener 2019-11-22 15:11:11 +05:30
66a1156d5c Merge branch 'admin-profile' into 'master'
add admin profile avatar

See merge request mohit.panjvani/crater-web!62
2019-11-22 09:20:15 +00:00
1be2c7122e Merge branch 'fix-payment' into 'master'
Fix payment edit

See merge request mohit.panjvani/crater-web!61
2019-11-22 09:06:21 +00:00
e9218e4d21 add default-avatar and change hover icon 2019-11-22 12:42:03 +05:30
812afc2dab add avatar on account-settings 2019-11-21 18:45:22 +05:30
4ec34550ed add admin profile avatar 2019-11-21 11:59:23 +05:30
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
ca6ab997de refactor amount problem in payment 2019-11-20 18:20:05 +05:30
8b05909b74 fix customer email validation 2019-11-20 17:46:45 +05:30
1e6372cbb1 add due amount on invoice select 2019-11-20 16:57:31 +05:30
d29c343911 Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into fix-payment 2019-11-20 15:16:19 +05:30
f3ef51bffb fix edit payment issue 2019-11-20 15:15:52 +05:30
147 changed files with 5507 additions and 56773 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 && \
docker-php-ext-install bcmath ctype json gd mbstring pdo pdo_mysql tokenizer xml
# 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

@ -4,8 +4,6 @@ namespace Crater;
use Illuminate\Database\Eloquent\Model;
use Crater\User;
use Crater\Country;
use Crater\State;
use Crater\City;
class Address extends Model
{
@ -16,8 +14,8 @@ class Address extends Model
'name',
'address_street_1',
'address_street_2',
'city_id',
'state_id',
'city',
'state',
'country_id',
'zip',
'phone',
@ -35,14 +33,4 @@ class Address extends Model
{
return $this->belongsTo(Country::class);
}
public function state()
{
return $this->belongsTo(State::class);
}
public function city()
{
return $this->belongsTo(City::class);
}
}

View File

@ -1,18 +0,0 @@
<?php
namespace Crater;
use Illuminate\Database\Eloquent\Model;
use Crater\State;
class City extends Model
{
public function state()
{
return $this->belongsTo(State::class);
}
public function address()
{
return $this->hasMany(Address::class);
}
}

View File

@ -2,15 +2,9 @@
namespace Crater;
use Illuminate\Database\Eloquent\Model;
use Crater\State;
class Country extends Model
{
public function states()
{
return $this->hasMany(State::class);
}
public function address()
{
return $this->hasMany(Address::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

@ -24,6 +24,7 @@ class EstimateItem extends Model
'price' => 'integer',
'total' => 'integer',
'discount' => 'float',
'quantity' => 'float',
'discount_val' => 'integer',
'tax' => 'integer'
];

View File

@ -56,7 +56,7 @@ class CompanyController extends Controller
public function getAdminCompany()
{
$user = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city', 'company'])->find(1);
$user = User::with(['addresses', 'addresses.country', 'company'])->find(1);
return response()->json([
'user' => $user
@ -75,9 +75,9 @@ class CompanyController extends Controller
$company->addMediaFromRequest('logo')->toMediaCollection('logo');
}
$fields = $request->only(['address_street_1', 'address_street_2', 'city_id', 'state_id', 'country_id', 'zip', 'phone']);
$fields = $request->only(['address_street_1', 'address_street_2', 'city', 'state', 'country_id', 'zip', 'phone']);
$address = Address::updateOrCreate(['user_id' => 1], $fields);
$user = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city', 'company'])->find(1);
$user = User::with(['addresses', 'addresses.country', 'company'])->find(1);
return response()->json([
'user' => $user,
@ -153,6 +153,58 @@ 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
]);
}
public function updateSetting(SettingRequest $request)
{
CompanySetting::setSetting($request->key, $request->value, $request->header('company'));
@ -227,4 +279,32 @@ class CompanyController extends Controller
'success' => true
]);
}
/**
* Upload the Admin Avatar to public storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function uploadAdminAvatar(Request $request)
{
$data = json_decode($request->admin_avatar);
if($data) {
$user = auth()->user();
if($user) {
$user->clearMediaCollection('admin_avatar');
$user->addMediaFromBase64($data->data)
->usingFileName($data->name)
->toMediaCollection('admin_avatar');
}
}
return response()->json([
'user' => $user,
'success' => true
]);
}
}

View File

@ -80,8 +80,8 @@ class CustomersController extends Controller
$newAddress->name = $address["name"];
$newAddress->address_street_1 = $address["address_street_1"];
$newAddress->address_street_2 = $address["address_street_2"];
$newAddress->city_id = $address["city_id"];
$newAddress->state_id = $address["state_id"];
$newAddress->city = $address["city"];
$newAddress->state = $address["state"];
$newAddress->country_id = $address["country_id"];
$newAddress->zip = $address["zip"];
$newAddress->phone = $address["phone"];
@ -112,11 +112,7 @@ class CustomersController extends Controller
'billingAddress',
'shippingAddress',
'billingAddress.country',
'billingAddress.state',
'billingAddress.city',
'shippingAddress.country',
'shippingAddress.state',
'shippingAddress.city',
])->find($id);
return response()->json([
@ -160,6 +156,7 @@ class CustomersController extends Controller
if ($verifyEmail) {
if ($verifyEmail->id !== $customer->id) {
return response()->json([
'success' => false,
'error' => 'Email already in use'
]);
}
@ -180,14 +177,15 @@ 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"]]);
$newAddress->name = $address["name"];
$newAddress->address_street_1 = $address["address_street_1"];
$newAddress->address_street_2 = $address["address_street_2"];
$newAddress->city_id = $address["city_id"];
$newAddress->state_id = $address["state_id"];
$newAddress->city = $address["city"];
$newAddress->state = $address["state"];
$newAddress->country_id = $address["country_id"];
$newAddress->zip = $address["zip"];
$newAddress->phone = $address["phone"];

View File

@ -33,10 +33,14 @@ class EnvironmentController extends Controller
*/
public function saveDatabaseEnvironment(DatabaseEnvironmentRequest $request)
{
Artisan::call('config:clear');
Artisan::call('cache:clear');
$results = $this->EnvironmentManager->saveDatabaseVariables($request);
if(array_key_exists("success", $results)) {
Artisan::call('config:clear');
Artisan::call('cache:clear');
Artisan::call('storage:link');
Artisan::call('key:generate --force');
Artisan::call('migrate --seed --force');

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);
}
@ -216,26 +234,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 +291,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 +301,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);
}

View File

@ -90,7 +90,7 @@ class FrontendController extends Controller
}
}
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
$colors = [
'invoice_primary_color',
@ -189,7 +189,7 @@ class FrontendController extends Controller
}
}
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
$colors = [
'invoice_primary_color',
@ -262,7 +262,7 @@ class FrontendController extends Controller
$estimateTemplate = EstimateTemplate::find($estimate->estimate_template_id);
$company = Company::find($estimate->company_id);
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
$logo = $company->getMedia('logo')->first();
if($logo) {
@ -338,7 +338,7 @@ class FrontendController extends Controller
$invoiceTemplate = InvoiceTemplate::find($invoice->invoice_template_id);
$company = Company::find($invoice->company_id);
$companyAddress = User::with(['addresses', 'addresses.country', 'addresses.state', 'addresses.city'])->find(1);
$companyAddress = User::with(['addresses', 'addresses.country'])->find(1);
$logo = $company->getMedia('logo')->first();

View File

@ -66,14 +66,24 @@ class InvoicesController extends Controller
{
$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
]);
}
@ -85,6 +95,13 @@ class InvoicesController extends Controller
*/
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);
}
}
@ -222,12 +238,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()
]);
}
@ -240,6 +257,13 @@ class InvoicesController extends Controller
*/
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 +292,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 +316,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 +323,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 +334,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);
}
}

View File

@ -3,8 +3,6 @@ namespace Crater\Http\Controllers;
use Illuminate\Http\Request;
use Crater\Country;
use Crater\State;
use Crater\City;
class LocationController extends Controller
{
@ -14,18 +12,4 @@ class LocationController extends Controller
'countries' => Country::all()
]);
}
public function getStates($id)
{
return response()->json([
'states' => Country::find($id)->states
]);
}
public function getCities($id)
{
return response()->json([
'cities' => State::find($id)->cities
]);
}
}

View File

@ -58,8 +58,6 @@ class OnboardingController extends Controller
$user = User::with([
'addresses',
'addresses.country',
'addresses.state',
'addresses.city',
'company'
])->find(1);
@ -99,6 +97,32 @@ class OnboardingController extends Controller
]);
}
public function uploadAdminAvatar(Request $request)
{
$setting = Setting::getSetting('profile_complete');
if ($setting == '1' || $setting == 'COMPLETED') {
return response()->json(['error' => 'Profile already created.']);
}
$data = json_decode($request->admin_avatar);
if($data) {
$user = User::find($data->id);
if($user) {
$user->clearMediaCollection('admin_avatar');
$user->addMediaFromBase64($data->data)
->usingFileName($data->name)
->toMediaCollection('admin_avatar');
}
}
return response()->json([
'user' => $user,
'success' => true
]);
}
public function adminCompany(CompanyRequest $request)
{
$setting = Setting::getSetting('profile_complete');
@ -130,8 +154,8 @@ class OnboardingController extends Controller
$fields = $request->only([
'address_street_1',
'address_street_2',
'city_id',
'state_id',
'city',
'state',
'country_id',
'zip',
'phone'
@ -178,6 +202,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',
@ -214,7 +277,14 @@ class OnboardingController extends Controller
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

@ -10,6 +10,7 @@ use Carbon\Carbon;
use function MongoDB\BSON\toJSON;
use Crater\User;
use Crater\Http\Requests\PaymentRequest;
use Validator;
class PaymentController extends Controller
{
@ -50,13 +51,24 @@ 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
'nextPaymentNumberAttribute' => $nextPaymentNumberAttribute,
'nextPaymentNumber' => $payment_prefix.'-'.$nextPaymentNumber,
'payment_prefix' => $payment_prefix
]);
}
@ -68,6 +80,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,7 +109,7 @@ 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,
@ -135,7 +154,8 @@ class PaymentController extends Controller
'customers' => User::where('role', 'customer')
->whereCompany($request->header('company'))
->get(),
'nextPaymentNumber' => $payment->payment_number,
'nextPaymentNumber' => $payment->getPaymentNumAttribute(),
'payment_prefix' => $payment->getPaymentPrefixAttribute(),
'payment' => $payment,
'invoices' => $invoices
]);
@ -150,6 +170,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,7 +205,7 @@ 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;

View File

@ -83,8 +83,7 @@ class ReportController extends Controller
{
$company = Company::where('unique_hash', $hash)->first();
$items = InvoiceItem::with('item')
->whereCompany($company->id)
$items = InvoiceItem::whereCompany($company->id)
->applyInvoiceFilters($request->only(['from_date', 'to_date']))
->itemAttributes()
->get();

View File

@ -36,7 +36,6 @@ class CustomerRequest extends FormRequest
'name' => 'required',
'addresses.*.address_street_1' => 'max:255',
'addresses.*.address_street_2' => 'max:255',
'email' => 'email|nullable|unique:users,email,'.$this->id
];
break;
default:

View File

@ -25,11 +25,11 @@ class DatabaseEnvironmentRequest extends FormRequest
{
return [
'app_url' => 'required|url',
'database_connection' => 'required|string|max:50',
'database_hostname' => 'required|string|max:50',
'database_connection' => 'required|string',
'database_hostname' => 'required|string',
'database_port' => 'required|numeric',
'database_name' => 'required|string|max:50',
'database_username' => 'required|string|max:50',
'database_name' => 'required|string',
'database_username' => 'required|string',
];
}
}

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

@ -26,55 +26,55 @@ class MailEnvironmentRequest extends FormRequest
switch ($this->get('mail_driver')) {
case 'smtp':
return [
'mail_driver' => 'required|string|max:50',
'mail_host' => 'required|string|max:50',
'mail_port' => 'required|max:50',
'mail_driver' => 'required|string',
'mail_host' => 'required|string',
'mail_port' => 'required',
'mail_username' => 'required|string',
'mail_password' => 'required|string',
'mail_encryption' => 'required|string|max:50',
'from_name' => 'required|string|max:50',
'from_mail' => 'required|string|max:50',
'mail_encryption' => 'required|string',
'from_name' => 'required|string',
'from_mail' => 'required|string',
];
break;
case 'mailgun':
return [
'mail_driver' => 'required|string|max:50',
'mail_host' => 'required|string|max:50',
'mail_port' => 'required|max:50',
'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|max:50',
'from_name' => 'required|string|max:50',
'from_mail' => 'required|string|max:50',
'mail_encryption' => 'required|string',
'from_name' => 'required|string',
'from_mail' => 'required|string',
];
break;
case 'ses':
return [
'mail_driver' => 'required|string|max:50',
'mail_host' => 'required|string|max:50',
'mail_port' => 'required|max:50',
'mail_driver' => 'required|string',
'mail_host' => 'required|string',
'mail_port' => 'required',
'mail_ses_key' => 'required|string',
'mail_ses_secret' => 'required|string',
'mail_encryption' => 'required|string|max:50',
'from_name' => 'required|string|max:50',
'from_mail' => 'required|string|max:50',
'mail_encryption' => 'required|string',
'from_name' => 'required|string',
'from_mail' => 'required|string',
];
break;
case 'mail':
return [
'from_name' => 'required|string|max:50',
'from_mail' => 'required|string|max:50',
'from_name' => 'required|string',
'from_mail' => 'required|string',
];
break;
case 'sendmail':
return [
'from_name' => 'required|string|max:50',
'from_mail' => 'required|string|max:50',
'from_name' => 'required|string',
'from_mail' => 'required|string',
];
break;
}

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

@ -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.
@ -82,7 +86,7 @@ class Invoice extends Model
// So the substr returns this 000001
// Add the string in front and higher up the number.
// the %05d part makes sure that there are always 6 numbers in the string.
// the %06d part makes sure that there are always 6 numbers in the string.
// so it adds the missing zero's when needed.
return sprintf('%06d', intval($number) + 1);
@ -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

@ -30,6 +30,7 @@ class InvoiceItem extends Model
'price' => 'integer',
'total' => 'integer',
'discount' => 'float',
'quantity' => 'float',
'discount_val' => 'integer',
'tax' => 'integer'
];
@ -78,7 +79,8 @@ class InvoiceItem extends Model
public function scopeItemAttributes($query)
{
$query->select(
DB::raw('sum(quantity) as total_quantity, sum(total) as total_amount, item_id')
)->groupBy('item_id');
DB::raw('sum(quantity) as total_quantity, sum(total) as total_amount, invoice_items.name')
)->groupBy('invoice_items.name');
}
}

View File

@ -12,10 +12,10 @@ class Listener
* @param $event
* @return boolean
*/
protected function check($event)
protected function isListenerFired($event)
{
// Do not apply to the same or newer versions
if (version_compare(static::VERSION, $event->old, '>')) {
if (version_compare(static::VERSION, $event->old, '<=')) {
return true;
}

View File

@ -0,0 +1,115 @@
<?php
namespace Crater\Listeners\Updates\v1;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Crater\Events\UpdateFinished;
use Crater\Listeners\Updates\Listener;
use Crater\Setting;
use Crater\Currency;
class Version110 extends Listener
{
const VERSION = '1.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 currencies
$this->addCurrencies();
// Update Crater app version
Setting::setSetting('version', static::VERSION);
}
private function addCurrencies() {
$currencies = [
'13' => [
'symbol' => 'S$'
],
'16' => [
'symbol' => '₫'
],
'17' => [
'symbol' => 'Fr.'
],
'21' => [
'symbol' => '฿'
],
'22' => [
'symbol' => '₦'
],
'26' => [
'symbol' => 'HK$'
],
'35' => [
'symbol' => 'NAƒ'
],
'38' => [
'symbol' => 'GH₵'
],
'39' => [
'symbol' => 'Лв.'
],
'42' => [
'symbol' => 'RON'
],
'44' => [
'symbol' => 'SِAR'
],
'46' => [
'symbol' => 'Rf'
],
'47' => [
'symbol' => '₡'
],
'54' => [
'symbol' => '‎د.ت'
],
'55' => [
'symbol' => '₽'
],
'57' => [
'symbol' => 'ر.ع.'
],
'58' => [
'symbol' => '₴'
],
];
foreach ($currencies as $key => $currency) {
Currency::updateOrCreate(['id' => $key], $currency);
}
Currency::create([
'name' => 'Kuwaiti Dinar',
'code' => 'KWD',
'symbol' => 'KWD ',
'precision' => '3',
'thousand_separator' => ',',
'decimal_separator' => '.'
]);
}
}

View File

@ -0,0 +1,109 @@
<?php
namespace Crater\Listeners\Updates\v2;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Database\Schema\Blueprint;
use Crater\Listeners\Updates\Listener;
use Crater\Events\UpdateFinished;
use Crater\Setting;
use Crater\Address;
class Version200 extends Listener
{
const VERSION = '2.0.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;
}
// Replace state and city id to name
$this->replaceStateAndCityName();
// Drop states and cities foreign key
$this->dropForeignKey();
// Remove states and cities tables
$this->dropSchemas();
// Delete state & city models, migrations & seeders
$this->deleteFiles();
// Update Crater app version
$this->updateVersion();
}
private function replaceStateAndCityName() {
\Schema::table('addresses', function (Blueprint $table) {
$table->string('state')->nullable();
$table->string('city')->nullable();
});
$addresses = \Crater\Address::all();
foreach ($addresses as $add) {
$city = \Crater\City::find($add->city_id);
if($city) {
$add->city = $city->name;
}
$state = \Crater\State::find($add->state_id);
if($state) {
$add->state = $state->name;
}
$add->save();
}
}
private function dropForeignKey() {
\Schema::table('addresses', function (Blueprint $table) {
$table->dropForeign('addresses_state_id_foreign');
$table->dropForeign('addresses_city_id_foreign');
$table->dropColumn('state_id');
$table->dropColumn('city_id');
});
}
private function dropSchemas() {
\Schema::disableForeignKeyConstraints();
\Schema::dropIfExists('states');
\Schema::dropIfExists('cities');
\Schema::enableForeignKeyConstraints();
}
private function deleteFiles() {
\File::delete(
database_path('migrations/2017_05_06_172817_create_cities_table.php'),
database_path('migrations/2017_05_06_173711_create_states_table.php'),
database_path('seeds/StatesTableSeeder.php'),
database_path('seeds/CitiesTableSeeder.php'),
app_path('City.php'),
app_path('State.php')
);
}
private function updateVersion() {
Setting::setSetting('version', static::VERSION);
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace Crater\Listeners\Updates\v2;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Database\Schema\Blueprint;
use Crater\Events\UpdateFinished;
use Crater\Listeners\Updates\Listener;
use Crater\Setting;
class Version201 extends Listener
{
const VERSION = '2.0.1';
/**
* 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;
}
// Remove the language files
$this->removeLanguageFiles();
// Change estimate & invoice migrations
$this->changeMigrations();
// Update Crater app version
Setting::setSetting('version', static::VERSION);
}
private function removeLanguageFiles() {
$en = resource_path('assets/js/plugins/en.js');
$es = resource_path('assets/js/plugins/es.js');
$fr = resource_path('assets/js/plugins/fr.js');
if(file_exists($en)) {
unlink($en);
}
if(file_exists($es)) {
unlink($es);
}
if(file_exists($fr)) {
unlink($fr);
}
}
private function changeMigrations()
{
\Schema::table('invoices', function (Blueprint $table) {
$table->decimal('discount', 15, 2)->nullable()->change();
});
\Schema::table('estimates', function (Blueprint $table) {
$table->decimal('discount', 15, 2)->nullable()->change();
});
\Schema::table('invoice_items', function (Blueprint $table) {
$table->decimal('quantity', 15, 2)->change();
$table->decimal('discount', 15, 2)->nullable()->change();
});
\Schema::table('estimate_items', function (Blueprint $table) {
$table->decimal('quantity', 15, 2)->change();
$table->decimal('discount', 15, 2)->nullable()->change();
$table->unsignedBigInteger('discount_val')->nullable()->change();
});
}
}

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

@ -32,10 +32,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 +78,13 @@ 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);

View File

@ -5,6 +5,11 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvi
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
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;
class EventServiceProvider extends ServiceProvider
{
@ -15,6 +20,11 @@ class EventServiceProvider extends ServiceProvider
*/
protected $listen = [
UpdateFinished::class=> [
Version110::class,
Version200::class,
Version201::class,
Version202::class,
Version210::class,
],
Registered::class => [
SendEmailVerificationNotification::class,

View File

@ -48,17 +48,21 @@ class EnvironmentManager
'DB_USERNAME='.$request->database_username."\n".
'DB_PASSWORD='.$request->database_password."\n\n";
if (! $this->checkDatabaseConnection($request)) {
try {
return [
'error' => 'connection_failed'
];
} else {
if(count(DB::connection()->select('SHOW TABLES'))) {
$this->checkDatabaseConnection($request);
if(\Schema::hasTable('users') ) {
return [
'error' => 'database_should_be_empty'
];
}
} catch (Exception $e) {
return [
'error_message' => $e->getMessage()
];
}
try {
@ -118,8 +122,6 @@ class EnvironmentManager
);
}
} catch (Exception $e) {
return [
'error' => 'mail_variables_save_error'
@ -316,12 +318,6 @@ class EnvironmentManager
],
]);
try {
DB::connection()->getPdo();
return true;
} catch (Exception $e) {
return false;
}
return DB::connection()->getPdo();
}
}

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,

View File

@ -1,25 +0,0 @@
<?php
namespace Crater;
use Illuminate\Database\Eloquent\Model;
use Crater\City;
use Crater\Country;
use Crater\Address;
class State extends Model
{
public function cities()
{
return $this->hasMany(City::class);
}
public function country()
{
return $this->belongsTo(Country::class);
}
public function address()
{
return $this->hasMany(Address::class);
}
}

View File

@ -51,7 +51,8 @@ class User extends Authenticatable implements HasMedia
];
protected $appends = [
'formattedCreatedAt'
'formattedCreatedAt',
'avatar'
];
/**
@ -244,4 +245,13 @@ class User extends Authenticatable implements HasMedia
return true;
}
public function getAvatarAttribute()
{
$avatar = $this->getMedia('admin_avatar')->first();
if ($avatar) {
return asset($avatar->getUrl());
}
return ;
}
}

View File

@ -10,6 +10,7 @@
"require": {
"php": "^7.2",
"barryvdh/laravel-dompdf": "^0.8.1",
"doctrine/dbal": "^2.10",
"fideloper/proxy": "^4.0",
"guzzlehttp/guzzle": "^6.3",
"intervention/image": "^2.3",

484
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2a5e8d91a2be3144e2812dd708dc14b7",
"content-hash": "e7cf4f0a8e1e7d60cc72b34ed4c730ce",
"packages": [
{
"name": "barryvdh/laravel-dompdf",
@ -158,6 +158,247 @@
"description": "implementation of xdg base directory specification for php",
"time": "2014-10-24T07:27:01+00:00"
},
{
"name": "doctrine/cache",
"version": "v1.8.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/d4374ae95b36062d02ef310100ed33d78738d76c",
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c",
"shasum": ""
},
"require": {
"php": "~7.1"
},
"conflict": {
"doctrine/common": ">2.2,<2.4"
},
"require-dev": {
"alcaeus/mongo-php-adapter": "^1.1",
"doctrine/coding-standard": "^4.0",
"mongodb/mongodb": "^1.1",
"phpunit/phpunit": "^7.0",
"predis/predis": "~1.0"
},
"suggest": {
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.8.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Caching library offering an object-oriented API for many cache backends",
"homepage": "https://www.doctrine-project.org",
"keywords": [
"cache",
"caching"
],
"time": "2019-10-28T09:31:32+00:00"
},
{
"name": "doctrine/dbal",
"version": "v2.10.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
"shasum": ""
},
"require": {
"doctrine/cache": "^1.0",
"doctrine/event-manager": "^1.0",
"ext-pdo": "*",
"php": "^7.2"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
"jetbrains/phpstorm-stubs": "^2019.1",
"phpstan/phpstan": "^0.11.3",
"phpunit/phpunit": "^8.4.1",
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
},
"bin": [
"bin/doctrine-dbal"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.10.x-dev",
"dev-develop": "3.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\DBAL\\": "lib/Doctrine/DBAL"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
}
],
"description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
"homepage": "https://www.doctrine-project.org/projects/dbal.html",
"keywords": [
"abstraction",
"database",
"db2",
"dbal",
"mariadb",
"mssql",
"mysql",
"oci8",
"oracle",
"pdo",
"pgsql",
"postgresql",
"queryobject",
"sasql",
"sql",
"sqlanywhere",
"sqlite",
"sqlserver",
"sqlsrv"
],
"time": "2019-11-03T16:50:43+00:00"
},
{
"name": "doctrine/event-manager",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/event-manager.git",
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3",
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"conflict": {
"doctrine/common": "<2.9@dev"
},
"require-dev": {
"doctrine/coding-standard": "^4.0",
"phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Common\\": "lib/Doctrine/Common"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"description": "Doctrine Event Manager component",
"homepage": "https://www.doctrine-project.org/projects/event-manager.html",
"keywords": [
"event",
"eventdispatcher",
"eventmanager"
],
"time": "2018-06-11T11:59:03+00:00"
},
{
"name": "doctrine/inflector",
"version": "v1.3.0",
@ -5307,247 +5548,6 @@
],
"time": "2019-05-27T17:52:04+00:00"
},
{
"name": "doctrine/cache",
"version": "v1.8.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/d4374ae95b36062d02ef310100ed33d78738d76c",
"reference": "d4374ae95b36062d02ef310100ed33d78738d76c",
"shasum": ""
},
"require": {
"php": "~7.1"
},
"conflict": {
"doctrine/common": ">2.2,<2.4"
},
"require-dev": {
"alcaeus/mongo-php-adapter": "^1.1",
"doctrine/coding-standard": "^4.0",
"mongodb/mongodb": "^1.1",
"phpunit/phpunit": "^7.0",
"predis/predis": "~1.0"
},
"suggest": {
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.8.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Caching library offering an object-oriented API for many cache backends",
"homepage": "https://www.doctrine-project.org",
"keywords": [
"cache",
"caching"
],
"time": "2019-10-28T09:31:32+00:00"
},
{
"name": "doctrine/dbal",
"version": "v2.10.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
"reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934",
"shasum": ""
},
"require": {
"doctrine/cache": "^1.0",
"doctrine/event-manager": "^1.0",
"ext-pdo": "*",
"php": "^7.2"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
"jetbrains/phpstorm-stubs": "^2019.1",
"phpstan/phpstan": "^0.11.3",
"phpunit/phpunit": "^8.4.1",
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
},
"bin": [
"bin/doctrine-dbal"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.10.x-dev",
"dev-develop": "3.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\DBAL\\": "lib/Doctrine/DBAL"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
}
],
"description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
"homepage": "https://www.doctrine-project.org/projects/dbal.html",
"keywords": [
"abstraction",
"database",
"db2",
"dbal",
"mariadb",
"mssql",
"mysql",
"oci8",
"oracle",
"pdo",
"pgsql",
"postgresql",
"queryobject",
"sasql",
"sql",
"sqlanywhere",
"sqlite",
"sqlserver",
"sqlsrv"
],
"time": "2019-11-03T16:50:43+00:00"
},
{
"name": "doctrine/event-manager",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/event-manager.git",
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3",
"reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"conflict": {
"doctrine/common": "<2.9@dev"
},
"require-dev": {
"doctrine/coding-standard": "^4.0",
"phpunit/phpunit": "^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Common\\": "lib/Doctrine/Common"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
},
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"description": "Doctrine Event Manager component",
"homepage": "https://www.doctrine-project.org/projects/event-manager.html",
"keywords": [
"event",
"eventdispatcher",
"eventmanager"
],
"time": "2018-06-11T11:59:03+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.2.0",

View File

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

View File

@ -4,11 +4,11 @@ return [
/*
|--------------------------------------------------------------------------
| Crater Requirements
| Crater Configuration
|--------------------------------------------------------------------------
|
*/
'version' => '1.0.0',
'version' => '2.1.0',
];

View File

@ -51,7 +51,7 @@ return [
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'strict' => false,
'engine' => null,
],

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

@ -10,9 +10,9 @@ $factory->define(Address::class, function (Faker $faker) {
'name' => $faker->name,
'address_street_1' => $faker->streetAddress,
'address_street_2' => $faker->streetAddress,
'city_id' => 5909,
'state_id' => 42,
'country_id' => 1,
'city' => $faker->city,
'state' => $faker->state,
'country_id' => 231,
'zip' => $faker->postcode,
'phone' => $faker->phoneNumber,
'fax' => $faker->phoneNumber,

View File

@ -25,7 +25,7 @@ class CreateInvoicesTable extends Migration
$table->string('discount_per_item');
$table->text('notes')->nullable();
$table->string('discount_type')->nullable();
$table->unsignedBigInteger('discount')->nullable();
$table->decimal('discount', 15, 2)->nullable();
$table->unsignedBigInteger('discount_val')->nullable();
$table->unsignedBigInteger('sub_total');
$table->unsignedBigInteger('total');

View File

@ -18,10 +18,10 @@ class CreateInvoiceItemsTable extends Migration
$table->string('name');
$table->string('description')->nullable();
$table->string('discount_type');
$table->unsignedBigInteger('quantity');
$table->unsignedBigInteger('price');
$table->decimal('quantity', 15, 2);
$table->decimal('discount', 15, 2)->nullable();
$table->unsignedBigInteger('discount_val');
$table->unsignedBigInteger('discount');
$table->unsignedBigInteger('tax');
$table->unsignedBigInteger('total');
$table->integer('invoice_id')->unsigned();

View File

@ -23,8 +23,8 @@ class CreateEstimatesTable extends Migration
$table->string('tax_per_item');
$table->string('discount_per_item');
$table->string('notes')->nullable();
$table->decimal('discount', 15, 2)->nullable();
$table->string('discount_type')->nullable();
$table->unsignedBigInteger('discount')->nullable();
$table->unsignedBigInteger('discount_val')->nullable();
$table->unsignedBigInteger('sub_total');
$table->unsignedBigInteger('total');

View File

@ -1,33 +0,0 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCitiesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('cities', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id')->index();
$table->string('name');
$table->integer('state_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('cities');
}
}

View File

@ -1,32 +0,0 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateStatesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('states', function (Blueprint $table) {
$table->increments('id')->index();
$table->string('name');
$table->integer('country_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('states');
}
}

View File

@ -18,9 +18,9 @@ class CreateEstimateItemsTable extends Migration
$table->string('name');
$table->string('description')->nullable();
$table->string('discount_type');
$table->unsignedBigInteger('quantity');
$table->unsignedBigInteger('discount');
$table->unsignedBigInteger('discount_val');
$table->decimal('quantity', 15, 2);
$table->decimal('discount', 15, 2)->nullable();
$table->unsignedBigInteger('discount_val')->nullable();
$table->unsignedBigInteger('price');
$table->unsignedBigInteger('tax');
$table->unsignedBigInteger('total');

View File

@ -18,10 +18,8 @@ class CreateAddressesTable extends Migration
$table->string('name')->nullable();
$table->string('address_street_1')->nullable();
$table->string('address_street_2')->nullable();
$table->integer('city_id')->unsigned()->nullable();
$table->foreign('city_id')->references('id')->on('cities');
$table->integer('state_id')->unsigned()->nullable();
$table->foreign('state_id')->references('id')->on('states');
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->integer('country_id')->unsigned()->nullable();
$table->foreign('country_id')->references('id')->on('countries');
$table->string('zip')->nullable();

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();
});

File diff suppressed because it is too large Load Diff

View File

@ -122,7 +122,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Singapore Dollar',
'code' => 'SGD',
'symbol' => '',
'symbol' => 'S$',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -147,7 +147,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Vietnamese Dong',
'code' => 'VND',
'symbol' => '',
'symbol' => '',
'precision' => '0',
'thousand_separator' => '.',
'decimal_separator' => ','
@ -155,7 +155,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Swiss Franc',
'code' => 'CHF',
'symbol' => '',
'symbol' => 'Fr.',
'precision' => '2',
'thousand_separator' => '\'',
'decimal_separator' => '.'
@ -187,7 +187,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Thai Baht',
'code' => 'THB',
'symbol' => '',
'symbol' => '฿',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -195,7 +195,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Nigerian Naira',
'code' => 'NGN',
'symbol' => '',
'symbol' => '',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -227,7 +227,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Hong Kong Dollar',
'code' => 'HKD',
'symbol' => '',
'symbol' => 'HK$',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -299,7 +299,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Netherlands Antillean Guilder',
'code' => 'ANG',
'symbol' => '',
'symbol' => 'NAƒ',
'precision' => '2',
'thousand_separator' => '.',
'decimal_separator' => ','
@ -323,7 +323,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Ghanaian Cedi',
'code' => 'GHS',
'symbol' => '',
'symbol' => 'GH₵',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -331,7 +331,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Bulgarian Lev',
'code' => 'BGN',
'symbol' => '',
'symbol' => 'Лв.',
'precision' => '2',
'thousand_separator' => ' ',
'decimal_separator' => '.'
@ -355,7 +355,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Romanian New Leu',
'code' => 'RON',
'symbol' => '',
'symbol' => 'RON',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -371,7 +371,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Saudi Riyal',
'code' => 'SAR',
'symbol' => '',
'symbol' => 'SِAR',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -387,7 +387,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Maldivian Rufiyaa',
'code' => 'MVR',
'symbol' => '',
'symbol' => 'Rf',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -395,7 +395,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Costa Rican Colón',
'code' => 'CRC',
'symbol' => '',
'symbol' => '',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -454,7 +454,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Tunisian Dinar',
'code' => 'TND',
'symbol' => '',
'symbol' => '‎د.ت',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -462,7 +462,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Russian Ruble',
'code' => 'RUB',
'symbol' => '',
'symbol' => '',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -479,7 +479,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Omani Rial',
'code' => 'OMR',
'symbol' => '',
'symbol' => 'ر.ع.',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'
@ -487,7 +487,7 @@ class CurrenciesTableSeeder extends Seeder
[
'name' => 'Ukrainian Hryvnia',
'code' => 'UAH',
'symbol' => '',
'symbol' => '',
'precision' => '2',
'thousand_separator' => ',',
'decimal_separator' => '.'

View File

@ -14,8 +14,6 @@ class DatabaseSeeder extends Seeder
$this->call(CurrenciesTableSeeder::class);
$this->call(RoleSeeder::class);
$this->call(CountriesTableSeeder::class);
$this->call(StatesTableSeeder::class);
$this->call(CitiesTableSeeder::class);
$this->call(EstimateTemplateSeeder::class);
$this->call(InvoiceTemplateSeeder::class);
}

File diff suppressed because it is too large Load Diff

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;
}
}
}

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -1,4 +1,4 @@
{
"/assets/js/app.js": "/assets/js/app.js?id=0de16e5183b0d24fd95d",
"/assets/css/crater.css": "/assets/css/crater.css?id=361d275866b6299acb36"
"/assets/js/app.js": "/assets/js/app.js?id=a9f802b3fe774e87bf0c",
"/assets/css/crater.css": "/assets/css/crater.css?id=193e5770a0e7a8604f35"
}

View File

@ -14,7 +14,8 @@ Web Application is made using Laravel & VueJS while the Mobile Apps are built us
4. [Discord](#discord)
5. [Roadmap](#roadmap)
6. [Credits](#credits)
7. [License](#license)
7. [Help us translate](#translate)
8. [License](#license)
## Documentation
@ -28,11 +29,11 @@ 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
Join the Crater discord server to discuss:
Join the Crater discord server to discuss:
[Invite Link](https://discord.gg/nyTstm6)
## Roadmap
@ -59,6 +60,13 @@ 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)
## Translate
Help us translate on [Transifex](https://www.transifex.com/bytefury/crater-invoice)
## License
Crater is released under the Attribution Assurance License.
See [LICENSE](LICENSE) for details.

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

@ -55,6 +55,7 @@
v-model="currency"
:options="currencies"
:searchable="true"
:allow-empty="false"
:show-labels="false"
:placeholder="$t('customers.select_currency')"
label="name"
@ -163,15 +164,10 @@
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7">
<base-select
v-model="billingState"
:options="billingStates"
:searchable="true"
:show-labels="false"
:placeholder="$t('general.select_state')"
:disabled="isDisabledBillingState"
track-by="id"
label="name"
<base-input
v-model="billing.state"
type="text"
name="billingState"
/>
</div>
</div>
@ -179,29 +175,14 @@
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7">
<base-select
v-model="billingCity"
:options="billingCities"
:searchable="true"
:show-labels="false"
:placeholder="$t('general.select_city')"
:disabled="isDisabledBillingCity"
track-by="id"
label="name"
<base-input
v-model="billing.city"
type="text"
name="billingCity"
/>
</div>
</div>
<!-- <div class="form-group row">
<label class="col-sm-4 col-form-label">Zip Code</label>
<div class="col-sm-7">
<base-input
v-model="billing.zip"
type="text"
/>
</div>
</div> -->
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.zip_code') }}</label>
<div class="col-sm-7">
@ -294,15 +275,10 @@
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.state') }}</label>
<div class="col-sm-7">
<base-select
v-model="shippingState"
:options="shippingStates"
:searchable="true"
:show-labels="false"
:placeholder="$t('general.select_state')"
:disabled="isDisabledShippingState"
track-by="id"
label="name"
<base-input
v-model="shipping.state"
type="text"
name="shippingState"
/>
</div>
</div>
@ -310,15 +286,10 @@
<div class="form-group row">
<label class="col-sm-4 col-form-label input-label">{{ $t('customers.city') }}</label>
<div class="col-sm-7">
<base-select
v-model="shippingCity"
:options="shippingCities"
:searchable="true"
:show-labels="false"
:placeholder="$t('general.select_city')"
:disabled="isDisabledShippingCity"
track-by="id"
label="name"
<base-input
v-model="shipping.city"
type="text"
name="shippingCity"
/>
</div>
</div>
@ -372,16 +343,8 @@ export default {
return {
isLoading: false,
countryList: [],
billingStates: [],
billingCities: [],
billingCountry: null,
billingState: null,
billingCity: null,
shippingStates: [],
shippingCities: [],
shippingCountry: null,
shippingState: null,
shippingCity: null,
isCopyFromBilling: false,
currencyList: [],
currency: '',
@ -442,61 +405,14 @@ export default {
billingCountry () {
if (this.billingCountry) {
this.billing.country_id = this.billingCountry.id
this.isDisabledBillingState = false
this.fetchBillingStates(this.billingCountry.id)
this.billingState = null
this.billingCity = null
return true
}
},
billingState () {
if (this.billingState) {
this.billing.state_id = this.billingState.id
this.isDisabledBillingCity = false
this.fetchBillingCities(this.billingState.id)
this.billingCity = null
return true
}
this.billingCity = null
this.isDisabledBillingCity = true
},
billingCity () {
if (this.billingCity) {
this.billing.city_id = this.billingCity.id
}
},
shippingCountry () {
if (this.shippingCountry) {
this.shipping.country_id = this.shippingCountry.id
this.isDisabledShippingState = false
this.fetchShippingStates(this.shippingCountry.id)
if (this.isCopyFromBilling) {
return true
}
this.shippingState = null
this.shippingCity = null
return true
}
},
shippingState () {
if (this.shippingState) {
this.shipping.state_id = this.shippingState.id
this.isDisabledShippingCity = false
this.fetchShippingCities(this.shippingState.id)
if (this.isCopyFromBilling) {
this.isCopyFromBilling = false
return true
}
this.shippingCity = null
return true
}
this.shippingCity = null
this.isDisabledShippingCity = true
},
shippingCity () {
if (this.shippingCity) {
this.shipping.city_id = this.shippingCity.id
}
}
},
mounted () {
@ -529,16 +445,8 @@ export default {
addresses: []
}
this.billingStates = []
this.billingCities = []
this.billingCountry = null
this.billingState = null
this.billingCity = null
this.shippingStates = []
this.shippingCities = []
this.shippingCountry = null
this.shippingState = null
this.shippingCity = null
this.billing = {...AddressStub}
this.shipping = {...AddressStub}
@ -553,13 +461,9 @@ export default {
this.isCopyFromBilling = true
this.shipping = {...this.billing, type: 'shipping'}
this.shippingCountry = this.billingCountry
this.shippingState = this.billingState
this.shippingCity = this.billingCity
} else {
this.shipping = {...AddressStub, type: 'shipping'}
this.shippingCountry = null
this.shippingState = null
this.shippingCity = null
}
},
async loadData () {
@ -633,30 +537,6 @@ export default {
if (res) {
this.countryList = res.data.countries
}
},
async fetchBillingStates (id) {
let res = await window.axios.get(`/api/states/${id}`)
if (res) {
this.billingStates = res.data.states
}
},
async fetchBillingCities (id) {
let res = await window.axios.get(`/api/cities/${id}`)
if (res) {
this.billingCities = res.data.cities
}
},
async fetchShippingStates (id) {
let res = await window.axios.get(`/api/states/${id}`)
if (res) {
this.shippingStates = res.data.states
}
},
async fetchShippingCities (id) {
let res = await window.axios.get(`/api/cities/${id}`)
if (res) {
this.shippingCities = res.data.cities
}
}
}
}

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

@ -87,5 +87,16 @@ export default {
} catch (e) {
console.log(e)
}
},
checkValidUrl (url) {
let pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
'(\\#[-a-z\\d_]*)?$', 'i') // fragment locator
return !!pattern.test(url)
}
}

View File

@ -1,818 +0,0 @@
export default {
navigation: {
// key : 'singular | plural'
dashboard: 'Dashboard',
customers: 'Customers',
items: 'Items',
invoices: 'Invoices',
expenses: 'Expenses',
estimates: 'Estimates',
payments: 'Payments',
reports: 'Reports',
settings: 'Settings',
logout: 'Logout'
},
general: {
view_pdf: 'View PDF',
download_pdf: 'Download PDF',
save: 'Save',
cancel: 'Cancel',
update: 'Update',
download: 'Download',
from_date: 'From Date',
to_date: 'To Date',
from: 'From',
to: 'To',
go_back: 'Go Back',
back_to_login: 'Back to Login?',
home: 'Home',
filter: 'Filter',
delete: 'Delete',
edit: 'Edit',
view: 'View',
add_new_item: 'Add New Item',
clear_all: 'Clear All',
showing: 'Showing',
of: 'of',
actions: 'Actions',
subtotal: 'SUBTOTAL',
discount: 'DISCOUNT',
fixed: 'Fixed',
percentage: 'Percentage',
tax: 'TAX',
total_amount: 'TOTAL AMOUNT',
bill_to: 'Bill to',
ship_to: 'Ship to',
due: 'Due',
draft: 'Draft',
sent: 'Sent',
all: 'All',
select_all: 'Select All',
choose_file: 'Click here to choose a file',
choose_template: 'Choose a template',
choose: 'Choose',
remove: 'Remove',
powered_by: 'Powered by',
bytefury: 'Bytefury',
select_a_status: 'Select a status',
select_a_tax: 'Select a tax',
search: 'Search',
are_you_sure: 'Are you sure?',
list_is_empty: 'List is empty.',
no_tax_found: 'No tax found!',
four_zero_four: '404',
you_got_lost: 'Whoops! You got Lost!',
go_home: 'Go Home',
setting_updated: 'Setting updated successfully',
select_state: 'Select state',
select_country: 'Select Country',
select_city: 'Select City',
street_1: 'Street 1',
street_2: 'Street 2',
action_failed: 'Action Failed'
},
dashboard: {
select_year: 'Select year',
cards: {
due_amount: 'Amount Due',
customers: 'Customers',
invoices: 'Invoices',
estimates: 'Estimates'
},
chart_info: {
total_sales: 'Sales',
total_receipts: 'Receipts',
total_expense: 'Expenses',
net_income: 'Net Income',
year: 'Select year'
},
weekly_invoices: {
title: 'Weekly Invoices'
},
monthly_chart: {
title: 'Sales & Expenses'
},
recent_invoices_card: {
title: 'Due Invoices',
due_on: 'Due On',
customer: 'Customer',
amount_due: 'Amount Due',
actions: 'Actions',
view_all: 'View All'
},
recent_estimate_card: {
title: 'Recent Estimates',
date: 'Date',
customer: 'Customer',
amount_due: 'Amount Due',
actions: 'Actions',
view_all: 'View All'
}
},
tax_types: {
name: 'Name',
description: 'Description',
percent: 'Percent',
compound_tax: 'Compound Tax'
},
customers: {
title: 'Customers',
add_customer: 'Add Customer',
contacts_list: 'Customer List',
name: 'Name',
display_name: 'Display Name',
primary_contact_name: 'Primary Contact Name',
contact_name: 'Contact Name',
amount_due: 'Amount Due',
email: 'Email',
address: 'Address',
phone: 'Phone',
website: 'Website',
country: 'Country',
state: 'State',
city: 'City',
zip_code: 'Zip Code',
added_on: 'Added On',
action: 'Action',
password: 'Password',
street_number: 'Street Number',
primary_currency: 'Primary Currency',
add_new_customer: 'Add New Customer',
save_customer: 'Save Customer',
update_customer: 'Update Customer',
customer: 'Customer | Customers',
new_customer: 'New Customer',
edit_customer: 'Edit Customer',
basic_info: 'Basic Info',
billing_address: 'Billing Address',
shipping_address: 'Shipping Address',
copy_billing_address: 'Copy from Billing',
no_customers: 'No customers yet!',
no_customers_found: 'No customers found!',
list_of_customers: 'This section will contain the list of customers.',
primary_display_name: 'Primary Display Name',
select_currency: 'Select currency',
select_a_customer: 'Select a customer',
type_or_click: 'Type or click to select',
confirm_delete: 'You will not be able to recover this Customer | You will not be able to recover these Customers',
created_message: 'Customer created successfully',
updated_message: 'Customer updated successfully',
deleted_message: 'Customer deleted successfully | Customers deleted successfully'
},
items: {
title: 'Items',
items_list: 'Items List',
name: 'Name',
unit: 'Unit',
description: 'Description',
added_on: 'Added On',
price: 'Price',
date_of_creation: 'Date Of Creation',
action: 'Action',
add_item: 'Add Item',
save_item: 'Save Item',
update_item: 'Update Item',
item: 'Item | Items',
add_new_item: 'Add New Item',
new_item: 'New Item',
edit_item: 'Edit Item',
no_items: 'No items yet!',
list_of_items: 'This section will contain the list of items.',
select_a_unit: 'select unit',
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',
updated_message: 'Item updated successfully',
deleted_message: 'Item deleted successfully | Items deleted successfully'
},
estimates: {
title: 'Estimates',
estimate: 'Estimate | Estimates',
estimates_list: 'Estimates List',
days: '{days} Days',
months: '{months} Month',
years: '{years} Year',
all: 'All',
paid: 'Paid',
unpaid: 'Unpaid',
customer: 'CUSTOMER',
ref_no: 'REF NO.',
number: 'NUMBER',
amount_due: 'AMOUNT DUE',
partially_paid: 'Partially Paid',
total: 'Total',
discount: 'Discount',
sub_total: 'Sub Total',
estimate_number: 'Estimate Number',
ref_number: 'Ref Number',
contact: 'Contact',
add_item: 'Add an Item',
date: 'Date',
due_date: 'Due Date',
expiry_date: 'Expiry Date',
status: 'Status',
add_tax: 'Add Tax',
amount: 'Amount',
action: 'Action',
notes: 'Notes',
tax: 'Tax',
estimate_template: 'Template',
convert_to_invoice: 'Convert to Invoice',
mark_as_sent: 'Mark as Sent',
send_estimate: 'Send Estimate',
record_payment: 'Record Payment',
add_estimate: 'Add Estimate',
save_estimate: 'Save Estimate',
confirm_conversion: 'You want to convert this Estimate into 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',
confirm_mark_as_accepted: 'This estimate will be marked as Accepted',
confirm_mark_as_rejected: 'This estimate will be marked as Rejected',
no_matching_estimates: 'There are no matching estimates!',
mark_as_sent_successfully: 'Estimate marked as sent successfully',
send_estimate_successfully: 'Estimate sent successfully',
errors: {
required: 'Field is required'
},
accepted: 'Accepted',
sent: 'Sent',
draft: 'Draft',
declined: 'Declined',
new_estimate: 'New Estimate',
add_new_estimate: 'Add New Estimate',
update_Estimate: 'Update Estimate',
edit_estimate: 'Edit Estimate',
items: 'items',
Estimate: 'Estimate | Estimates',
add_new_tax: 'Add New Tax',
no_estimates: 'No estimates yet!',
list_of_estimates: 'This section will contain the list of estimates.',
mark_as_rejected: 'Mark as rejected',
mark_as_accepted: 'Mark as accepted',
marked_as_accepted_message: 'Estimate marked as accepted',
marked_as_rejected_message: 'Estimate marked as rejected',
confirm_delete: 'You will not be able to recover this Estimate | You will not be able to recover these Estimates',
created_message: 'Estimate created successfully',
updated_message: 'Estimate updated successfully',
deleted_message: 'Estimate deleted successfully | Estimates deleted successfully',
user_email_does_not_exist: 'User email does not exist',
something_went_wrong: 'something went wrong',
item: {
title: 'Item Title',
description: 'Description',
quantity: 'Quantity',
price: 'Price',
discount: 'Discount',
total: 'Total',
total_discount: 'Total Discount',
sub_total: 'Sub Total',
tax: 'Tax',
amount: 'Amount',
select_an_item: 'Type or click to select an item',
type_item_description: 'Type Item Description (optional)'
}
},
invoices: {
title: 'Invoices',
invoices_list: 'Invoices List',
days: '{days} Days',
months: '{months} Month',
years: '{years} Year',
all: 'All',
paid: 'Paid',
unpaid: 'Unpaid',
customer: 'CUSTOMER',
paid_status: 'PAID STATUS',
ref_no: 'REF NO.',
number: 'NUMBER',
amount_due: 'AMOUNT DUE',
partially_paid: 'Partially Paid',
total: 'Total',
discount: 'Discount',
sub_total: 'Sub Total',
invoice: 'Invoice | Invoices',
invoice_number: 'Invoice Number',
ref_number: 'Ref Number',
contact: 'Contact',
add_item: 'Add an Item',
date: 'Date',
due_date: 'Due Date',
status: 'Status',
add_tax: 'Add Tax',
amount: 'Amount',
action: 'Action',
notes: 'Notes',
view: 'View',
send_invoice: 'Send Invoice',
invoice_template: 'Invoice Template',
template: 'Template',
mark_as_sent: 'Mark as sent',
confirm_send_invoice: 'This invoice will be sent via email to the customer',
invoice_mark_as_sent: 'This invoice will be marked as sent',
confirm_send: 'This invoice will be sent via email to the customer',
invoice_date: 'Invoice Date',
record_payment: 'Record Payment',
add_new_invoice: 'Add New Invoice',
update_expense: 'Update Expense',
edit_invoice: 'Edit Invoice',
new_invoice: 'New Invoice',
save_invoice: 'Save Invoice',
update_invoice: 'Update Invoice',
add_new_tax: 'Add New Tax',
no_invoices: 'No Invoices yet!',
list_of_invoices: 'This section will contain the list of invoices.',
select_invoice: 'Select Invoice',
no_matching_invoices: 'There are no matching invoices!',
mark_as_sent_successfully: 'Invoice marked as sent successfully',
send_invoice_successfully: 'Invoice sent successfully',
item: {
title: 'Item Title',
description: 'Description',
quantity: 'Quantity',
price: 'Price',
discount: 'Discount',
total: 'Total',
total_discount: 'Total Discount',
sub_total: 'Sub Total',
tax: 'Tax',
amount: 'Amount',
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',
updated_message: 'Invoice updated successfully',
deleted_message: 'Invoice deleted successfully | Invoices deleted successfully',
marked_as_sent_message: 'Invoice marked as sent successfully',
user_email_does_not_exist: 'User email does not exist',
something_went_wrong: 'something went wrong',
invalid_due_amount_message: 'Total Invoice amount cannot be less than total paid amount for this Invoice. Please update the invoice or delete the associated payments to continue.'
},
credit_notes: {
title: 'Credit Notes',
credit_notes_list: 'Credit Notes List',
// Fields
credit_notes: 'Credit Notes',
contact: 'Contact',
date: 'Date',
amount: 'Amount',
action: 'Action',
credit_number: 'Credit Number',
notes: 'Notes',
confirm_delete: 'Do you want to delete this credit note?',
item: {
title: 'Item Title',
description: 'Description',
quantity: 'Quantity',
price: 'Price',
discount: 'Discount',
total: 'Total',
total_discount: 'Total Discount',
sub_total: 'Sub Total',
tax: 'Tax'
}
},
payments: {
title: 'Payments',
payments_list: 'Payments List',
record_payment: 'Record Payment',
// Fields
customer: 'Customer',
date: 'Date',
amount: 'Amount',
action: 'Action',
payment_number: 'Payment Number',
payment_mode: 'Payment Mode',
invoice: 'Invoice',
note: 'Note',
add_payment: 'Add Payment',
new_payment: 'New Payment',
edit_payment: 'Edit Payment',
view_payment: 'View Payment',
add_new_payment: 'Add New Payment',
save_payment: 'Save Payment',
update_payment: 'Update Payment',
payment: 'Payment | Payments',
no_payments: 'No payments yet!',
list_of_payments: 'This section will contain the list of payments.',
select_payment_mode: 'Select payment mode',
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',
updated_message: 'Payment updated successfully',
deleted_message: 'Payment deleted successfully | Payments deleted successfully',
invalid_amount_message: 'Payment amount is invalid'
},
expenses: {
title: 'Expenses',
expenses_list: 'Expenses List',
// Fields
expense_title: 'Title',
contact: 'Contact',
category: 'Category',
from_date: 'From Date',
to_date: 'To Date',
expense_date: 'Date',
description: 'Description',
receipt: 'Receipt',
amount: 'Amount',
action: 'Action',
note: 'Note',
category_id: 'Category Id',
date: 'Expense Date',
add_expense: 'Add Expense',
add_new_expense: 'Add New Expense',
save_expense: 'Save Expense',
update_expense: 'Update Expense',
download_receipt: 'Download Receipt',
edit_expense: 'Edit Expense',
new_expense: 'New Expense',
expense: 'Expense | Expenses',
no_expenses: 'No expenses yet!',
list_of_expenses: 'This section will contain the list of expenses.',
confirm_delete: 'You will not be able to recover this Expense | You will not be able to recover these Expenses',
created_message: 'Expense created successfully',
updated_message: 'Expense updated successfully',
deleted_message: 'Expense deleted successfully | Expenses deleted successfully',
categories: {
categories_list: 'Categories List',
title: 'Title',
name: 'Name',
description: 'Description',
amount: 'Amount',
actions: 'Actions',
add_category: 'Add Category',
new_category: 'New Category',
category: 'Category | Categories',
select_a_category: 'Select a category'
}
},
login: {
email: 'Email',
password: 'Password',
forgot_password: 'Forgot Password?',
or_signIn_with: 'or Sign in with:',
login: 'Login',
register: 'Register',
reset_password: 'Reset Password',
password_reset_successfully: 'Password Reset Successfully',
enter_email: 'Enter email',
enter_password: 'Enter Password',
retype_password: 'Retype Password',
login_placeholder: 'mail@example.com'
},
reports: {
title: 'Report',
from_date: 'From Date',
to_date: 'To Date',
status: 'Status',
paid: 'Paid',
unpaid: 'Unpaid',
download_pdf: 'Download PDF',
view_pdf: 'View PDF',
update_report: 'Update Report',
report: 'Report | Reports',
profit_loss: {
profit_loss: 'Profit & Loss',
to_date: 'To Date',
from_date: 'From Date',
date_range: 'Select Date Range'
},
sales: {
sales: 'Sales',
date_range: 'Select Date Range',
to_date: 'To Date',
from_date: 'From Date',
report_type: 'Report Type'
},
taxes: {
taxes: 'Taxes',
to_date: 'To Date',
from_date: 'From Date',
date_range: 'Select Date Range'
},
errors: {
required: 'Field is required'
},
invoices: {
invoice: 'Invoice',
invoice_date: 'Invoice Date',
due_date: 'Due Date',
amount: 'Amount',
contact_name: 'Contact Name',
status: 'Status'
},
estimates: {
estimate: 'Estimate',
estimate_date: 'Estimate Date',
due_date: 'Due Date',
estimate_number: 'Estimate Number',
ref_number: 'Ref Number',
amount: 'Amount',
contact_name: 'Contact Name',
status: 'Status'
},
expenses: {
expenses: 'Expenses',
category: 'Category',
date: 'Date',
amount: 'Amount',
to_date: 'To Date',
from_date: 'From Date',
date_range: 'Select Date Range'
}
},
settings: {
menu_title: {
account_settings: 'Account Settings',
company_information: 'Company Information',
preferences: 'Preferences',
notifications: 'Notifications',
tax_types: 'Tax Types',
expense_category: 'Expense Categories',
update_app: 'Update App'
},
title: 'Settings',
setting: 'Settings | Settings',
general: 'General',
language: 'Language',
primary_currency: 'Primary Currency',
timezone: 'Time Zone',
date_format: 'Date Format',
currencies: {
title: 'Currencies',
currency: 'Currency | Currencies',
currencies_list: 'Currencies List',
select_currency: 'Select Currency',
name: 'Name',
code: 'Code',
symbol: 'Symbol',
precision: 'Precision',
thousand_separator: 'Thousand Separator',
decimal_separator: 'Decimal Separator',
position: 'Position',
position_of_symbol: 'Position Of Symbol',
right: 'Right',
left: 'Left',
action: 'Action',
add_currency: 'Add Currency'
},
mail: {
host: 'Mail Host',
port: 'Mail Port',
driver: 'Mail Driver',
secret: 'Secret',
mailgun_secret: 'Mailgun Secret',
mailgun_domain: 'Domain',
mailgun_endpoint: 'Mailgun Endpoint',
ses_secret: 'SES Secret',
ses_key: 'SES Key',
password: 'Mail Password',
username: 'Mail Username',
mail_config: 'Mail Configuration',
from_name: 'From Mail Name',
from_mail: 'From Mail Address',
encryption: 'Mail Encryption',
mail_config_desc: 'Below is the form for Configuring Email driver for sending emails from the app. You can also configure third party providers like Sendgrid, SES etc.'
},
pdf: {
title: 'PDF Setting',
footer_text: 'Footer Text',
pdf_layout: 'PDF Layout'
},
company_info: {
company_info: 'Company info',
company_name: 'Company Name',
company_logo: 'Company Logo',
section_description: 'Information about your company that will be displayed on invoices, estimates and other documents created by Crater.',
phone: 'Phone',
country: 'Country',
state: 'State',
city: 'City',
address: 'Address',
zip: 'Zip',
save: 'Save',
updated_message: 'Company information updated successfully'
},
account_settings: {
name: 'Name',
email: 'Email',
password: 'Password',
confirm_password: 'Confirm Password',
account_settings: 'Account Settings',
save: 'Save',
section_description: 'You can update your name, email & password using the form below.',
updated_message: 'Account Settings updated successfully'
},
user_profile: {
name: 'Name',
email: 'Email',
password: 'Password',
confirm_password: 'Confirm Password'
},
notification: {
title: 'Notification',
email: 'Send Notifications to',
description: 'Which email notifications would you like to receive when something changes?',
invoice_viewed: 'Invoice viewed',
invoice_viewed_desc: 'When your customer views the invoice sent via crater dashboard.',
estimate_viewed: 'Estimate viewed',
estimate_viewed_desc: 'When your customer views the estimate sent via crater dashboard.',
save: 'Save',
email_save_message: 'Email saved successfully',
please_enter_email: 'Please Enter Email'
},
tax_types: {
title: 'Tax Types',
add_tax: 'Add Tax',
description: 'You can add or Remove Taxes as you please. Crater supports Taxes on Individual Items as well as on the invoice.',
add_new_tax: 'Add New Tax',
tax_settings: 'Tax Settings',
tax_per_item: 'Tax Per Item',
tax_name: 'Tax Name',
compound_tax: 'Compound Tax',
percent: 'Percent',
action: 'Action',
tax_setting_description: 'Enable this if you want to add taxes to individual invoice items. By default, taxes are added directly to the invoice.',
created_message: 'Tax type created successfully',
updated_message: 'Tax type updated successfully',
deleted_message: 'Tax type deleted successfully',
confirm_delete: 'You will not be able to recover this Tax Type',
already_in_use: 'Tax is already in use'
},
expense_category: {
title: 'Expense Categories',
action: 'Action',
description: 'Categories are required for adding expense entries. You can Add or Remove these categories according to your preference.',
add_new_category: 'Add New Category',
category_name: 'Category Name',
category_description: 'Description',
created_message: 'Expense Category created successfully',
deleted_message: 'Expense category deleted successfully',
updated_message: 'Expense category updated successfully',
confirm_delete: 'You will not be able to recover this Expense Category',
already_in_use: 'Category is already in use'
},
preferences: {
currency: 'Currency',
language: 'Language',
time_zone: 'Time Zone',
fiscal_year: 'Financial Year',
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.',
save: 'Save',
preference: 'Preference | Preferences',
general_settings: 'Default preferences for the system.',
updated_message: 'Preferences updated successfully',
select_language: 'select language',
select_time_zone: 'select Time Zone',
select_date_formate: 'select Date Formate',
select_financial_year: 'select financial year'
},
update_app: {
title: 'Update App',
description: 'You can easily update Crater by checking for a new update by clicking the button below',
check_update: 'Check for updates',
avail_update: 'New Update available',
next_version: 'Next version',
update: 'Update Now',
update_progress: 'Update in progress...',
progress_text: 'It will just take a few minutes. Please do not refresh the screen or close the window before the update finishes',
update_success: 'App has been updated successfully',
latest_message: 'No update available! You are on the latest version.',
current_version: 'Current Version'
}
},
wizard: {
account_info: 'Account Information',
account_info_desc: 'Below details will be used to create the main Administrator account. Also you can change the details anytime after logging in.',
name: 'Name',
email: 'Email',
password: 'Password',
confirm_password: 'Confirm Password',
save_cont: 'Save & Continue',
company_info: 'Company Information',
company_info_desc: 'This information will be displayed on invoices. Note that you can edit this later on settings page.',
company_name: 'Company Name',
company_logo: 'Company Logo',
logo_preview: 'Logo Preview',
preferences: 'Preferences',
preferences_desc: 'Default preferences for the system.',
country: 'Country',
state: 'State',
city: 'City',
address: 'Address',
street: 'Street1' | 'Street2',
phone: 'Phone',
zip_code: 'Zip Code',
go_back: 'Go Back',
currency: 'Currency',
language: 'Language',
time_zone: 'Time Zone',
fiscal_year: 'Financial Year',
date_format: 'Date Format',
from_address: 'From Address',
username: 'Username',
next: 'Next',
continue: 'Continue',
skip: 'Skip',
database: {
database: 'Site URL & Database',
connection: 'Database Connection',
host: 'Database Host',
port: 'Database Port',
password: 'Database Password',
app_url: 'App URL',
username: 'Database Username',
db_name: 'Database Name',
desc: 'Create a database on your server and set the credentials using the form below.'
},
permissions: {
permissions: 'Permissions',
permission_desc: 'Below is the list of folder permissions which are required in order for the app to work. If the permission check fails, make sure to update your folder permissions.'
},
mail: {
host: 'Mail Host',
port: 'Mail Port',
driver: 'Mail Driver',
secret: 'Secret',
mailgun_secret: 'Mailgun Secret',
mailgun_domain: 'Domain',
mailgun_endpoint: 'Mailgun Endpoint',
ses_secret: 'SES Secret',
ses_key: 'SES Key',
password: 'Mail Password',
username: 'Mail Username',
mail_config: 'Mail Configuration',
from_name: 'From Mail Name',
from_mail: 'From Mail Address',
encryption: 'Mail Encryption',
mail_config_desc: 'Below is the form for Configuring Email driver for sending emails from the app. You can also configure third party providers like Sendgrid, SES etc.'
},
req: {
system_req: 'System Requirements',
php_req_version: 'Php (version {version} required)',
check_req: 'Check Requirements',
system_req_desc: 'Crater has a few server requirements. Make sure that your server has the required php version and all the extensions mentioned below.'
},
errors: {
migrate_failed: 'Migrate Failed',
database_variables_save_error: 'Unable to connect to the DB with Provided Values.',
mail_variables_save_error: 'Email configuration failed.',
connection_failed: 'Database connection failed',
database_should_be_empty: 'Database should be empty'
},
success: {
mail_variables_save_successfully: 'Email configured successfully',
database_variables_save_successfully: 'Database configured successfully.'
}
},
layout_login: {
copyright_crater: 'Copyright @ Crater - 2019',
super_simple_invoicing: 'Super Simple Invoicing',
for_freelancer: 'for Freelancers &',
small_businesses: 'Small Businesses ',
crater_help: 'Crater helps you track expenses, record payments & generate beautiful',
invoices_and_estimates: 'invoices & estimates with ability to choose multiple templates.'
},
validation: {
invalid_url: 'Invalid url (ex: http://www.crater.com)',
required: 'Field is required',
email_incorrect: 'Incorrect Email.',
email_already_taken: 'The email has already been taken.',
email_does_not_exist: "User with given email doesn't exist",
send_reset_link: 'Send Reset Link',
not_yet: 'Not yet? Send it again',
password_min_length: 'Password must contain {count} characters',
name_min_length: 'Name must have at least {count} letters.',
enter_valid_tax_rate: 'Enter valid tax rate',
numbers_only: 'Numbers Only.',
characters_only: 'Characters Only.',
password_incorrect: 'Passwords must be identical',
password_length: 'Password must be {count} character long.',
qty_must_greater_than_zero: 'Quantity must be greater than zero.',
price_greater_than_zero: 'Price must be greater than zero.',
payment_greater_than_zero: 'Payment must be greater than zero.',
payment_greater_than_due_amount: 'Entered Payment is more than due amount of this invoice.',
quantity_maxlength: 'Quantity should not be greater than 20 digits.',
price_maxlength: 'Price should not be greater than 20 digits.',
price_minvalue: 'Price should be greater than 0.',
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.',
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.'
}
}

View File

@ -0,0 +1,880 @@
{
"navigation": {
"dashboard": "Dashboard",
"customers": "Customers",
"items": "Items",
"invoices": "Invoices",
"expenses": "Expenses",
"estimates": "Estimates",
"payments": "Payments",
"reports": "Reports",
"settings": "Settings",
"logout": "Logout"
},
"general": {
"view_pdf": "View PDF",
"download_pdf": "Download PDF",
"save": "Save",
"cancel": "Cancel",
"update": "Update",
"download": "Download",
"from_date": "From Date",
"to_date": "To Date",
"from": "From",
"to": "To",
"go_back": "Go Back",
"back_to_login": "Back to Login?",
"home": "Home",
"filter": "Filter",
"delete": "Delete",
"edit": "Edit",
"view": "View",
"add_new_item": "Add New Item",
"clear_all": "Clear All",
"showing": "Showing",
"of": "of",
"actions": "Actions",
"subtotal": "SUBTOTAL",
"discount": "DISCOUNT",
"fixed": "Fixed",
"percentage": "Percentage",
"tax": "TAX",
"total_amount": "TOTAL AMOUNT",
"bill_to": "Bill to",
"ship_to": "Ship to",
"due": "Due",
"draft": "Draft",
"sent": "Sent",
"all": "All",
"select_all": "Select All",
"choose_file": "Click here to choose a file",
"choose_template": "Choose a template",
"choose": "Choose",
"remove": "Remove",
"powered_by": "Powered by",
"bytefury": "Bytefury",
"select_a_status": "Select a status",
"select_a_tax": "Select a tax",
"search": "Search",
"are_you_sure": "Are you sure?",
"list_is_empty": "List is empty.",
"no_tax_found": "No tax found!",
"four_zero_four": "404",
"you_got_lost": "Whoops! You got Lost!",
"go_home": "Go Home",
"setting_updated": "Setting updated successfully",
"select_state": "Select state",
"select_country": "Select Country",
"select_city": "Select City",
"street_1": "Street 1",
"street_2": "Street 2",
"action_failed": "Action Failed"
},
"dashboard": {
"select_year": "Select year",
"cards": {
"due_amount": "Amount Due",
"customers": "Customers",
"invoices": "Invoices",
"estimates": "Estimates"
},
"chart_info": {
"total_sales": "Sales",
"total_receipts": "Receipts",
"total_expense": "Expenses",
"net_income": "Net Income",
"year": "Select year"
},
"weekly_invoices": {
"title": "Weekly Invoices"
},
"monthly_chart": {
"title": "Sales & Expenses"
},
"recent_invoices_card": {
"title": "Due Invoices",
"due_on": "Due On",
"customer": "Customer",
"amount_due": "Amount Due",
"actions": "Actions",
"view_all": "View All"
},
"recent_estimate_card": {
"title": "Recent Estimates",
"date": "Date",
"customer": "Customer",
"amount_due": "Amount Due",
"actions": "Actions",
"view_all": "View All"
}
},
"tax_types": {
"name": "Name",
"description": "Description",
"percent": "Percent",
"compound_tax": "Compound Tax"
},
"customers": {
"title": "Customers",
"add_customer": "Add Customer",
"contacts_list": "Customer List",
"name": "Name",
"display_name": "Display Name",
"primary_contact_name": "Primary Contact Name",
"contact_name": "Contact Name",
"amount_due": "Amount Due",
"email": "Email",
"address": "Address",
"phone": "Phone",
"website": "Website",
"country": "Country",
"state": "State",
"city": "City",
"zip_code": "Zip Code",
"added_on": "Added On",
"action": "Action",
"password": "Password",
"street_number": "Street Number",
"primary_currency": "Primary Currency",
"add_new_customer": "Add New Customer",
"save_customer": "Save Customer",
"update_customer": "Update Customer",
"customer": "Customer | Customers",
"new_customer": "New Customer",
"edit_customer": "Edit Customer",
"basic_info": "Basic Info",
"billing_address": "Billing Address",
"shipping_address": "Shipping Address",
"copy_billing_address": "Copy from Billing",
"no_customers": "No customers yet!",
"no_customers_found": "No customers found!",
"list_of_customers": "This section will contain the list of customers.",
"primary_display_name": "Primary Display Name",
"select_currency": "Select currency",
"select_a_customer": "Select a customer",
"type_or_click": "Type or click to select",
"confirm_delete": "You will not be able to recover this Customer | You will not be able to recover these Customers",
"created_message": "Customer created successfully",
"updated_message": "Customer updated successfully",
"deleted_message": "Customer deleted successfully | Customers deleted successfully"
},
"items": {
"title": "Items",
"items_list": "Items List",
"name": "Name",
"unit": "Unit",
"description": "Description",
"added_on": "Added On",
"price": "Price",
"date_of_creation": "Date Of Creation",
"action": "Action",
"add_item": "Add Item",
"save_item": "Save Item",
"update_item": "Update Item",
"item": "Item | Items",
"add_new_item": "Add New Item",
"new_item": "New Item",
"edit_item": "Edit Item",
"no_items": "No items yet!",
"list_of_items": "This section will contain the list of items.",
"select_a_unit": "select unit",
"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",
"updated_message": "Item updated successfully",
"deleted_message": "Item deleted successfully | Items deleted successfully"
},
"estimates": {
"title": "Estimates",
"estimate": "Estimate | Estimates",
"estimates_list": "Estimates List",
"days": "{days} Days",
"months": "{months} Month",
"years": "{years} Year",
"all": "All",
"paid": "Paid",
"unpaid": "Unpaid",
"customer": "CUSTOMER",
"ref_no": "REF NO.",
"number": "NUMBER",
"amount_due": "AMOUNT DUE",
"partially_paid": "Partially Paid",
"total": "Total",
"discount": "Discount",
"sub_total": "Sub Total",
"estimate_number": "Estimate Number",
"ref_number": "Ref Number",
"contact": "Contact",
"add_item": "Add an Item",
"date": "Date",
"due_date": "Due Date",
"expiry_date": "Expiry Date",
"status": "Status",
"add_tax": "Add Tax",
"amount": "Amount",
"action": "Action",
"notes": "Notes",
"tax": "Tax",
"estimate_template": "Template",
"convert_to_invoice": "Convert to Invoice",
"mark_as_sent": "Mark as Sent",
"send_estimate": "Send Estimate",
"record_payment": "Record Payment",
"add_estimate": "Add Estimate",
"save_estimate": "Save Estimate",
"confirm_conversion": "You want to convert this Estimate into 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",
"confirm_mark_as_accepted": "This estimate will be marked as Accepted",
"confirm_mark_as_rejected": "This estimate will be marked as Rejected",
"no_matching_estimates": "There are no matching estimates!",
"mark_as_sent_successfully": "Estimate marked as sent successfully",
"send_estimate_successfully": "Estimate sent successfully",
"errors": {
"required": "Field is required"
},
"accepted": "Accepted",
"sent": "Sent",
"draft": "Draft",
"declined": "Declined",
"new_estimate": "New Estimate",
"add_new_estimate": "Add New Estimate",
"update_Estimate": "Update Estimate",
"edit_estimate": "Edit Estimate",
"items": "items",
"Estimate": "Estimate | Estimates",
"add_new_tax": "Add New Tax",
"no_estimates": "No estimates yet!",
"list_of_estimates": "This section will contain the list of estimates.",
"mark_as_rejected": "Mark as rejected",
"mark_as_accepted": "Mark as accepted",
"marked_as_accepted_message": "Estimate marked as accepted",
"marked_as_rejected_message": "Estimate marked as rejected",
"confirm_delete": "You will not be able to recover this Estimate | You will not be able to recover these Estimates",
"created_message": "Estimate created successfully",
"updated_message": "Estimate updated successfully",
"deleted_message": "Estimate deleted successfully | Estimates deleted successfully",
"user_email_does_not_exist": "User email does not exist",
"something_went_wrong": "something went wrong",
"item": {
"title": "Item Title",
"description": "Description",
"quantity": "Quantity",
"price": "Price",
"discount": "Discount",
"total": "Total",
"total_discount": "Total Discount",
"sub_total": "Sub Total",
"tax": "Tax",
"amount": "Amount",
"select_an_item": "Type or click to select an item",
"type_item_description": "Type Item Description (optional)"
}
},
"invoices": {
"title": "Invoices",
"invoices_list": "Invoices List",
"days": "{days} Days",
"months": "{months} Month",
"years": "{years} Year",
"all": "All",
"paid": "Paid",
"unpaid": "Unpaid",
"customer": "CUSTOMER",
"paid_status": "PAID STATUS",
"ref_no": "REF NO.",
"number": "NUMBER",
"amount_due": "AMOUNT DUE",
"partially_paid": "Partially Paid",
"total": "Total",
"discount": "Discount",
"sub_total": "Sub Total",
"invoice": "Invoice | Invoices",
"invoice_number": "Invoice Number",
"ref_number": "Ref Number",
"contact": "Contact",
"add_item": "Add an Item",
"date": "Date",
"due_date": "Due Date",
"status": "Status",
"add_tax": "Add Tax",
"amount": "Amount",
"action": "Action",
"notes": "Notes",
"view": "View",
"send_invoice": "Send Invoice",
"invoice_template": "Invoice Template",
"template": "Template",
"mark_as_sent": "Mark as sent",
"confirm_send_invoice": "This invoice will be sent via email to the customer",
"invoice_mark_as_sent": "This invoice will be marked as sent",
"confirm_send": "This invoice will be sent via email to the customer",
"invoice_date": "Invoice Date",
"record_payment": "Record Payment",
"add_new_invoice": "Add New Invoice",
"update_expense": "Update Expense",
"edit_invoice": "Edit Invoice",
"new_invoice": "New Invoice",
"save_invoice": "Save Invoice",
"update_invoice": "Update Invoice",
"add_new_tax": "Add New Tax",
"no_invoices": "No Invoices yet!",
"list_of_invoices": "This section will contain the list of invoices.",
"select_invoice": "Select Invoice",
"no_matching_invoices": "There are no matching invoices!",
"mark_as_sent_successfully": "Invoice marked as sent successfully",
"send_invoice_successfully": "Invoice sent successfully",
"item": {
"title": "Item Title",
"description": "Description",
"quantity": "Quantity",
"price": "Price",
"discount": "Discount",
"total": "Total",
"total_discount": "Total Discount",
"sub_total": "Sub Total",
"tax": "Tax",
"amount": "Amount",
"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",
"updated_message": "Invoice updated successfully",
"deleted_message": "Invoice deleted successfully | Invoices deleted successfully",
"marked_as_sent_message": "Invoice marked as sent successfully",
"user_email_does_not_exist": "User email does not exist",
"something_went_wrong": "something went wrong",
"invalid_due_amount_message": "Total Invoice amount cannot be less than total paid amount for this Invoice. Please update the invoice or delete the associated payments to continue."
},
"credit_notes": {
"title": "Credit Notes",
"credit_notes_list": "Credit Notes List",
"credit_notes": "Credit Notes",
"contact": "Contact",
"date": "Date",
"amount": "Amount",
"action": "Action",
"credit_number": "Credit Number",
"notes": "Notes",
"confirm_delete": "Do you want to delete this credit note?",
"item": {
"title": "Item Title",
"description": "Description",
"quantity": "Quantity",
"price": "Price",
"discount": "Discount",
"total": "Total",
"total_discount": "Total Discount",
"sub_total": "Sub Total",
"tax": "Tax"
}
},
"payments": {
"title": "Payments",
"payments_list": "Payments List",
"record_payment": "Record Payment",
"customer": "Customer",
"date": "Date",
"amount": "Amount",
"action": "Action",
"payment_number": "Payment Number",
"payment_mode": "Payment Mode",
"invoice": "Invoice",
"note": "Note",
"add_payment": "Add Payment",
"new_payment": "New Payment",
"edit_payment": "Edit Payment",
"view_payment": "View Payment",
"add_new_payment": "Add New Payment",
"save_payment": "Save Payment",
"update_payment": "Update Payment",
"payment": "Payment | Payments",
"no_payments": "No payments yet!",
"list_of_payments": "This section will contain the list of payments.",
"select_payment_mode": "Select payment mode",
"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",
"updated_message": "Payment updated successfully",
"deleted_message": "Payment deleted successfully | Payments deleted successfully",
"invalid_amount_message": "Payment amount is invalid"
},
"expenses": {
"title": "Expenses",
"expenses_list": "Expenses List",
"expense_title": "Title",
"contact": "Contact",
"category": "Category",
"from_date": "From Date",
"to_date": "To Date",
"expense_date": "Date",
"description": "Description",
"receipt": "Receipt",
"amount": "Amount",
"action": "Action",
"note": "Note",
"category_id": "Category Id",
"date": "Expense Date",
"add_expense": "Add Expense",
"add_new_expense": "Add New Expense",
"save_expense": "Save Expense",
"update_expense": "Update Expense",
"download_receipt": "Download Receipt",
"edit_expense": "Edit Expense",
"new_expense": "New Expense",
"expense": "Expense | Expenses",
"no_expenses": "No expenses yet!",
"list_of_expenses": "This section will contain the list of expenses.",
"confirm_delete": "You will not be able to recover this Expense | You will not be able to recover these Expenses",
"created_message": "Expense created successfully",
"updated_message": "Expense updated successfully",
"deleted_message": "Expense deleted successfully | Expenses deleted successfully",
"categories": {
"categories_list": "Categories List",
"title": "Title",
"name": "Name",
"description": "Description",
"amount": "Amount",
"actions": "Actions",
"add_category": "Add Category",
"new_category": "New Category",
"category": "Category | Categories",
"select_a_category": "Select a category"
}
},
"login": {
"email": "Email",
"password": "Password",
"forgot_password": "Forgot Password?",
"or_signIn_with": "or Sign in with",
"login": "Login",
"register": "Register",
"reset_password": "Reset Password",
"password_reset_successfully": "Password Reset Successfully",
"enter_email": "Enter email",
"enter_password": "Enter Password",
"retype_password": "Retype Password",
"login_placeholder": "mail@example.com"
},
"reports": {
"title": "Report",
"from_date": "From Date",
"to_date": "To Date",
"status": "Status",
"paid": "Paid",
"unpaid": "Unpaid",
"download_pdf": "Download PDF",
"view_pdf": "View PDF",
"update_report": "Update Report",
"report": "Report | Reports",
"profit_loss": {
"profit_loss": "Profit & Loss",
"to_date": "To Date",
"from_date": "From Date",
"date_range": "Select Date Range"
},
"sales": {
"sales": "Sales",
"date_range": "Select Date Range",
"to_date": "To Date",
"from_date": "From Date",
"report_type": "Report Type"
},
"taxes": {
"taxes": "Taxes",
"to_date": "To Date",
"from_date": "From Date",
"date_range": "Select Date Range"
},
"errors": {
"required": "Field is required"
},
"invoices": {
"invoice": "Invoice",
"invoice_date": "Invoice Date",
"due_date": "Due Date",
"amount": "Amount",
"contact_name": "Contact Name",
"status": "Status"
},
"estimates": {
"estimate": "Estimate",
"estimate_date": "Estimate Date",
"due_date": "Due Date",
"estimate_number": "Estimate Number",
"ref_number": "Ref Number",
"amount": "Amount",
"contact_name": "Contact Name",
"status": "Status"
},
"expenses": {
"expenses": "Expenses",
"category": "Category",
"date": "Date",
"amount": "Amount",
"to_date": "To Date",
"from_date": "From Date",
"date_range": "Select Date Range"
}
},
"settings": {
"menu_title": {
"account_settings": "Account Settings",
"company_information": "Company Information",
"customization": "Customization",
"preferences": "Preferences",
"notifications": "Notifications",
"tax_types": "Tax Types",
"expense_category": "Expense Categories",
"update_app": "Update App"
},
"title": "Settings",
"setting": "Settings | Settings",
"general": "General",
"language": "Language",
"primary_currency": "Primary Currency",
"timezone": "Time Zone",
"date_format": "Date Format",
"currencies": {
"title": "Currencies",
"currency": "Currency | Currencies",
"currencies_list": "Currencies List",
"select_currency": "Select Currency",
"name": "Name",
"code": "Code",
"symbol": "Symbol",
"precision": "Precision",
"thousand_separator": "Thousand Separator",
"decimal_separator": "Decimal Separator",
"position": "Position",
"position_of_symbol": "Position Of Symbol",
"right": "Right",
"left": "Left",
"action": "Action",
"add_currency": "Add Currency"
},
"mail": {
"host": "Mail Host",
"port": "Mail Port",
"driver": "Mail Driver",
"secret": "Secret",
"mailgun_secret": "Mailgun Secret",
"mailgun_domain": "Domain",
"mailgun_endpoint": "Mailgun Endpoint",
"ses_secret": "SES Secret",
"ses_key": "SES Key",
"password": "Mail Password",
"username": "Mail Username",
"mail_config": "Mail Configuration",
"from_name": "From Mail Name",
"from_mail": "From Mail Address",
"encryption": "Mail Encryption",
"mail_config_desc": "Below is the form for Configuring Email driver for sending emails from the app. You can also configure third party providers like Sendgrid, SES etc."
},
"pdf": {
"title": "PDF Setting",
"footer_text": "Footer Text",
"pdf_layout": "PDF Layout"
},
"company_info": {
"company_info": "Company info",
"company_name": "Company Name",
"company_logo": "Company Logo",
"section_description": "Information about your company that will be displayed on invoices, estimates and other documents created by Crater.",
"phone": "Phone",
"country": "Country",
"state": "State",
"city": "City",
"address": "Address",
"zip": "Zip",
"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": "Autogenerate 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": "Autogenerate 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": "Autogenerate 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"
}
},
"account_settings": {
"profile_picture": "Profile Picture",
"name": "Name",
"email": "Email",
"password": "Password",
"confirm_password": "Confirm Password",
"account_settings": "Account Settings",
"save": "Save",
"section_description": "You can update your name, email & password using the form below.",
"updated_message": "Account Settings updated successfully"
},
"user_profile": {
"name": "Name",
"email": "Email",
"password": "Password",
"confirm_password": "Confirm Password"
},
"notification": {
"title": "Notification",
"email": "Send Notifications to",
"description": "Which email notifications would you like to receive when something changes?",
"invoice_viewed": "Invoice viewed",
"invoice_viewed_desc": "When your customer views the invoice sent via crater dashboard.",
"estimate_viewed": "Estimate viewed",
"estimate_viewed_desc": "When your customer views the estimate sent via crater dashboard.",
"save": "Save",
"email_save_message": "Email saved successfully",
"please_enter_email": "Please Enter Email"
},
"tax_types": {
"title": "Tax Types",
"add_tax": "Add Tax",
"description": "You can add or Remove Taxes as you please. Crater supports Taxes on Individual Items as well as on the invoice.",
"add_new_tax": "Add New Tax",
"tax_settings": "Tax Settings",
"tax_per_item": "Tax Per Item",
"tax_name": "Tax Name",
"compound_tax": "Compound Tax",
"percent": "Percent",
"action": "Action",
"tax_setting_description": "Enable this if you want to add taxes to individual invoice items. By default, taxes are added directly to the invoice.",
"created_message": "Tax type created successfully",
"updated_message": "Tax type updated successfully",
"deleted_message": "Tax type deleted successfully",
"confirm_delete": "You will not be able to recover this Tax Type",
"already_in_use": "Tax is already in use"
},
"expense_category": {
"title": "Expense Categories",
"action": "Action",
"description": "Categories are required for adding expense entries. You can Add or Remove these categories according to your preference.",
"add_new_category": "Add New Category",
"category_name": "Category Name",
"category_description": "Description",
"created_message": "Expense Category created successfully",
"deleted_message": "Expense category deleted successfully",
"updated_message": "Expense category updated successfully",
"confirm_delete": "You will not be able to recover this Expense Category",
"already_in_use": "Category is already in use"
},
"preferences": {
"currency": "Currency",
"language": "Language",
"time_zone": "Time Zone",
"fiscal_year": "Financial Year",
"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 is added directly to the invoice.",
"save": "Save",
"preference": "Preference | Preferences",
"general_settings": "Default preferences for the system.",
"updated_message": "Preferences updated successfully",
"select_language": "select language",
"select_time_zone": "select Time Zone",
"select_date_formate": "select Date Formate",
"select_financial_year": "select financial year"
},
"update_app": {
"title": "Update App",
"description": "You can easily update Crater by checking for a new update by clicking the button below",
"check_update": "Check for updates",
"avail_update": "New Update available",
"next_version": "Next version",
"update": "Update Now",
"update_progress": "Update in progress...",
"progress_text": "It will just take a few minutes. Please do not refresh the screen or close the window before the update finishes",
"update_success": "App has been updated! Please wait while your browser window gets reloaded automatically.",
"latest_message": "No update available! You are on the latest version.",
"current_version": "Current Version"
}
},
"wizard": {
"account_info": "Account Information",
"account_info_desc": "Below details will be used to create the main Administrator account. Also you can change the details anytime after logging in.",
"name": "Name",
"email": "Email",
"password": "Password",
"confirm_password": "Confirm Password",
"save_cont": "Save & Continue",
"company_info": "Company Information",
"company_info_desc": "This information will be displayed on invoices. Note that you can edit this later on settings page.",
"company_name": "Company Name",
"company_logo": "Company Logo",
"logo_preview": "Logo Preview",
"preferences": "Preferences",
"preferences_desc": "Default preferences for the system.",
"country": "Country",
"state": "State",
"city": "City",
"address": "Address",
"street": "Street1 | Street2",
"phone": "Phone",
"zip_code": "Zip Code",
"go_back": "Go Back",
"currency": "Currency",
"language": "Language",
"time_zone": "Time Zone",
"fiscal_year": "Financial Year",
"date_format": "Date Format",
"from_address": "From Address",
"username": "Username",
"next": "Next",
"continue": "Continue",
"skip": "Skip",
"database": {
"database": "Site URL & Database",
"connection": "Database Connection",
"host": "Database Host",
"port": "Database Port",
"password": "Database Password",
"app_url": "App URL",
"username": "Database Username",
"db_name": "Database Name",
"desc": "Create a database on your server and set the credentials using the form below."
},
"permissions": {
"permissions": "Permissions",
"permission_confirm_title": "Are you sure you want to continue?",
"permission_confirm_desc": "Folder permission check failed",
"permission_desc": "Below is the list of folder permissions which are required in order for the app to work. If the permission check fails, make sure to update your folder permissions."
},
"mail": {
"host": "Mail Host",
"port": "Mail Port",
"driver": "Mail Driver",
"secret": "Secret",
"mailgun_secret": "Mailgun Secret",
"mailgun_domain": "Domain",
"mailgun_endpoint": "Mailgun Endpoint",
"ses_secret": "SES Secret",
"ses_key": "SES Key",
"password": "Mail Password",
"username": "Mail Username",
"mail_config": "Mail Configuration",
"from_name": "From Mail Name",
"from_mail": "From Mail Address",
"encryption": "Mail Encryption",
"mail_config_desc": "Below is the form for Configuring Email driver for sending emails from the app. You can also configure third party providers like Sendgrid, SES etc."
},
"req": {
"system_req": "System Requirements",
"php_req_version": "Php (version {version} required)",
"check_req": "Check Requirements",
"system_req_desc": "Crater has a few server requirements. Make sure that your server has the required php version and all the extensions mentioned below."
},
"errors": {
"migrate_failed": "Migrate Failed",
"database_variables_save_error": "Unable to connect to the DB with Provided Values.",
"mail_variables_save_error": "Email configuration failed.",
"connection_failed": "Database connection failed",
"database_should_be_empty": "Database should be empty"
},
"success": {
"mail_variables_save_successfully": "Email configured successfully",
"database_variables_save_successfully": "Database configured successfully."
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2019",
"super_simple_invoicing": "Super Simple Invoicing",
"for_freelancer": "for Freelancers &",
"small_businesses": "Small Businesses ",
"crater_help": "Crater helps you track expenses, record payments & generate beautiful",
"invoices_and_estimates": "invoices & estimates with ability to choose multiple templates."
},
"validation": {
"invalid_url": "Invalid url (ex: http://www.crater.com)",
"required": "Field is required",
"email_incorrect": "Incorrect Email.",
"email_already_taken": "The email has already been taken.",
"email_does_not_exist": "User with given email doesn't exist",
"send_reset_link": "Send Reset Link",
"not_yet": "Not yet? Send it again",
"password_min_length": "Password must contain {count} characters",
"name_min_length": "Name must have at least {count} letters.",
"enter_valid_tax_rate": "Enter valid tax rate",
"numbers_only": "Numbers Only.",
"characters_only": "Characters Only.",
"password_incorrect": "Passwords must be identical",
"password_length": "Password must be {count} character long.",
"qty_must_greater_than_zero": "Quantity must be greater than zero.",
"price_greater_than_zero": "Price must be greater than zero.",
"payment_greater_than_zero": "Payment must be greater than zero.",
"payment_greater_than_due_amount": "Entered Payment is more than due amount of this invoice.",
"quantity_maxlength": "Quantity should not be greater than 20 digits.",
"price_maxlength": "Price should not be greater than 20 digits.",
"price_minvalue": "Price should be greater than 0.",
"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.",
"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.",
"prefix_maxlength": "Prefix should not be greater than 5 characters."
}
}

View File

@ -1,812 +0,0 @@
export default {
navigation: {
// key : 'singular | plural'
dashboard: 'Tablero',
customers: 'Clientes',
items: 'Artículos',
invoices: 'Facturas',
expenses: 'Gastos',
estimates: 'Estimadas',
payments: 'Pagos',
reports: 'Informes',
settings: 'Configuraciones',
logout: 'Cerrar sesión'
},
general: {
view_pdf: 'Ver PDF',
download_pdf: 'Descargar PDF',
save: 'Salvar',
cancel: 'Cancelar',
update: 'Actualizar',
download: 'Descargar',
from_date: 'Partir de 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',
filter: 'Filtrar',
delete: 'Eliminar',
edit: 'Editar',
view: 'Ver',
add_new_item: 'Agregar ítem nuevo',
clear_all: 'Limpiar todo',
showing: 'Demostración',
of: 'de',
actions: 'Comportamiento',
subtotal: 'TOTAL PARCIAL',
discount: 'DESCUENTO',
fixed: 'Fija',
percentage: 'Porcentaje',
tax: 'IMPUESTO',
total_amount: 'CANTIDAD TOTAL',
bill_to: 'Cobrar a',
ship_to: 'Envie a',
due: 'Debida',
draft: 'Sequía',
sent: 'Expedida',
all: 'Todas',
select_all: 'Seleccionar todo',
choose_file: 'Haga clic aquí para elegir un archivo.',
choose_template: 'Elige una plantilla',
choose: 'Escoger',
remove: 'Eliminar',
powered_by: 'Energizado por',
bytefury: 'Bytefury',
select_a_status: 'Selecciona un estado',
select_a_tax: 'Selecciona un impuesto',
search: 'Buscar',
are_you_sure: '¿Estás seguro?',
list_is_empty: 'La lista esta vacía.',
no_tax_found: '¡No se encontraron impuestos!',
four_zero_four: '404',
you_got_lost: 'Whoops! ¡Te perdiste!',
go_home: 'Vete a casa',
setting_updated: 'Configuración actualizada con éxito',
select_state: 'Seleccione estado',
select_country: 'Seleccionar país',
select_city: 'Ciudad selecta',
street_1: 'Calle 1',
street_2: 'Calle # 2',
action_failed: 'Accion: Fallida'
},
dashboard: {
select_year: 'Seleccione año',
cards: {
due_amount: 'Monto adeudado',
customers: 'Clientes',
invoices: 'Facturas',
estimates: 'Estimadas'
},
chart_info: {
total_sales: 'Ventas',
total_receipts: 'Ingresos',
total_expense: 'Gastos',
net_income: 'Lngresos netos',
year: 'Seleccione año'
},
weekly_invoices: {
title: 'Facturas semanales'
},
monthly_chart: {
title: 'Gastos de venta'
},
recent_invoices_card: {
title: 'Facturas adeudadas',
due_on: 'Debido a',
customer: 'Cliente',
amount_due: 'Monto adeudado',
actions: 'Comportamiento',
view_all: 'Ver todo'
},
recent_estimate_card: {
title: 'Estimaciones recientes',
date: 'Fecha',
customer: 'Cliente',
amount_due: 'Monto adeudado',
actions: 'Comportamiento',
view_all: 'Ver todo'
}
},
tax_types: {
name: 'Nombre',
description: 'Descripción',
percent: 'Por ciento',
compound_tax: 'Impuesto compuesto'
},
customers: {
title: 'Clientes',
add_customer: 'Agregar cliente',
contacts_list: 'Lista de clientes',
name: 'Nombre',
display_name: 'Nombre para mostrar',
primary_contact_name: 'Nombre de contacto primario',
contact_name: 'Nombre de contacto',
amount_due: 'Monto adeudado',
email: 'Email',
address: 'Habla a',
phone: 'Teléfono',
website: 'Sitio web',
country: 'País',
state: 'Estado',
city: 'Ciudad',
zip_code: 'Código postal',
added_on: 'Añadido',
action: 'Acción',
password: 'Contraseña',
street_number: 'Número de calle',
primary_currency: 'Moneda primaria',
add_new_customer: 'Agregar nuevo cliente',
save_customer: 'Guardar cliente',
update_customer: 'Actualizar cliente',
customer: 'Cliente | Clientes',
new_customer: 'Nuevo cliente',
edit_customer: 'Editar cliente',
basic_info: 'Información básica',
billing_address: 'Dirección de Envio',
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!',
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',
confirm_delete: 'No podrá recuperar este cliente | No podrá recuperar estos clientes',
created_message: 'Cliente creado con éxito',
updated_message: 'Cliente actualizado con éxito',
deleted_message: 'Cliente eliminado correctamente | Clientes eliminados exitosamente'
},
items: {
title: 'Artículos',
items_list: 'Lista de artículos',
name: 'Nombre',
unit: 'Unidad',
description: 'Descripción',
added_on: 'Añadido',
price: 'Precio',
date_of_creation: 'Fecha de creación',
action: 'Acción',
add_item: 'Añadir artículo',
save_item: 'Guardar artículo',
update_item: 'Actualizar elemento',
item: 'Artículo | Artículos',
add_new_item: 'Agregar ítem nuevo',
new_item: 'Nuevo artículo',
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',
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',
created_message: 'Artículo creado con éxito',
updated_message: 'Artículo actualizado con éxito',
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',
months: '{meses} Mes',
years: '{años} Año',
all: 'Todas',
paid: 'Pagada',
unpaid: 'No pagado',
customer: 'CLIENTE',
ref_no: 'NÚMERO DE REFERENCIA.',
number: 'NÚMERO',
amount_due: 'CANTIDAD DEBIDA',
partially_paid: 'Parcialmente pagado',
total: 'Total',
discount: 'Descuento',
sub_total: 'Subtotal',
estimate_number: 'Numero Estimado',
ref_number: 'Número de referencia',
contact: 'Contacto',
add_item: 'Agregar un artículo',
date: 'Fecha',
due_date: 'Fecha de vencimiento',
expiry_date: 'Fecha de caducidad',
status: 'Estado',
add_tax: 'Agregar impuesto',
amount: 'Cantidad',
action: 'Acción',
notes: 'Notas',
tax: 'Impuesto',
send_estimate: 'Enviar presupuesto',
estimate_template: 'Plantilla de estimación',
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?',
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',
errors: {
required: 'Se requiere campo'
},
accepted: 'Aceptada',
sent: 'Expedida',
draft: 'Sequía',
declined: 'Rechazada',
new_estimate: 'Nueva estimación',
add_new_estimate: 'Añadir nuevo presupuesto',
update_Estimate: 'Actualizar presupuesto',
edit_estimate: 'Editar estimación',
items: 'artículos',
Estimate: 'Estimación | Estimados',
add_new_tax: 'Agregar nuevo impuesto',
no_estimates: '¡Aún no hay estimaciones!',
list_of_estimates: 'Esta sección contendrá la lista de estimaciones.',
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',
item: {
title: 'Título del artículo',
description: 'Descripción',
quantity: 'Quantity',
price: 'Precio',
discount: 'Descuento',
total: 'Total',
total_discount: 'Descuento total',
sub_total: 'Subtotal',
tax: 'Impuesto',
amount: 'Cantidad',
select_an_item: 'Escriba o haga clic para seleccionar un elemento',
type_item_description: 'Tipo Elemento Descripción (opcional)'
}
},
invoices: {
title: 'Facturas',
invoices_list: 'Lista de facturas',
days: '{días} días',
months: '{meses} Mes',
years: '{años} Año',
all: 'Todas',
paid: 'Pagada',
unpaid: 'No pagado',
customer: 'CLIENTE',
paid_status: 'ESTADO PAGADO',
ref_no: 'NÚMERO DE REFERENCIA.',
number: 'NÚMERO',
amount_due: 'CANTIDAD DEBIDA',
partially_paid: 'Parcialmente pagado',
total: 'Total',
discount: 'Descuento',
sub_total: 'Subtotal',
invoice: 'Factura | Facturas',
invoice_number: 'Numero de factura',
ref_number: 'Número de referencia',
contact: 'Contacto',
add_item: 'Agregar un artículo',
date: 'Fecha',
due_date: 'Fecha de vencimiento',
status: 'Estado',
add_tax: 'Agregar impuesto',
amount: 'Cantidad',
action: 'Acción',
notes: 'Notas',
view: 'Ver',
send_invoice: 'Enviará la factura',
invoice_template: 'Plantilla de factura',
template: 'Modelo',
mark_as_sent: 'Marcar como enviado',
invoice_mark_as_sent: 'Esta factura se marcará como enviada',
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',
edit_invoice: 'Editar factura',
new_invoice: 'Nueva factura',
save_invoice: 'Guardar factura',
update_invoice: 'Actualizar factura',
add_new_tax: 'Agregar nuevo impuesto',
no_invoices: '¡Aún no hay facturas!',
list_of_invoices: 'Esta sección contendrá la lista de facturas.',
select_invoice: 'Seleccionar factura',
mark_as_sent_successfully: 'Factura marcada como enviada con éxito',
send_invoice_successfully: 'Factura enviada exitosamente',
item: {
title: 'Título del artículo',
description: 'Descripción',
quantity: 'Cantidad',
price: 'Precio',
discount: 'Descuento',
total: 'Total',
total_discount: 'Descuento total',
sub_total: 'Subtotal',
tax: 'Impuesto',
amount: 'Cantidad',
select_an_item: 'Escriba o haga clic para seleccionar un elemento',
type_item_description: 'Tipo Elemento Descripción (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',
created_message: 'Factura creada exitosamente',
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'
},
credit_notes: {
title: 'Notas de credito',
credit_notes_list: 'Lista de notas de crédito',
// Fields
credit_notes: 'Notas de credito',
contact: 'Contacto',
date: 'Fecha',
amount: 'Cantidad',
action: 'Acción',
credit_number: 'Número de crédito',
notes: 'Notas',
confirm_delete: '¿Desea eliminar esta nota de crédito?',
item: {
title: 'Título del artículo',
description: 'Descripción',
quantity: 'Cantidad',
price: 'Precio',
discount: 'Descuento',
total: 'Total',
total_discount: 'Descuento total',
sub_total: 'Subtotal',
tax: 'Impuesto'
}
},
payments: {
title: 'Pagos',
payments_list: 'Lista de pagos',
record_payment: 'Registro de pago',
// Fields
customer: 'Cliente',
date: 'Fecha',
amount: 'Cantidad',
action: 'Acción',
payment_number: 'Numero de pago',
payment_mode: 'Modo de pago',
invoice: 'Factura',
note: 'Nota',
add_payment: 'Agregar pago',
new_payment: 'Nuevo pago',
edit_payment: 'Editar pago',
view_payment: 'Ver pago',
add_new_payment: 'Agregar nuevo pago',
save_payment: 'Guardar pago',
update_payment: 'Actualizar pago',
payment: 'Pago | Pagos',
no_payments: '¡Aún no hay pagos!',
list_of_payments: 'Esta sección contendrá la lista de pagos.',
select_payment_mode: 'Seleccionar modo de pago',
confirm_delete: 'No podrá recuperar este pago | No podrá recuperar estos pagos',
created_message: 'Pago creado con éxito',
updated_message: 'Pago actualizado con éxito',
deleted_message: 'Pago eliminado con éxito | Pagos eliminados exitosamente',
invalid_amount_message: 'El importe del pago no es válido.'
},
expenses: {
title: 'Gastos',
expenses_list: 'Lista de gastos',
// Fields
expense_title: 'Título',
contact: 'Contacto',
category: 'Categoría',
from_date: 'Partir de la fecha',
to_date: 'Hasta la fecha',
expense_date: 'Fecha',
description: 'Descripción',
receipt: 'Recibo',
amount: 'Cantidad',
action: 'Acción',
note: 'Nota',
category_id: 'Categoria ID',
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',
download_receipt: 'Descargar recibo',
edit_expense: 'Editar gasto',
new_expense: 'Nuevo gasto',
expense: 'Gastos | Gastos',
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',
created_message: 'Gastos creados exitosamente',
updated_message: 'Gastos actualizados con éxito',
deleted_message: 'Gastos eliminados con éxito | Gastos eliminados exitosamente',
categories: {
categories_list: 'Lista de categorías',
title: 'Título',
name: 'Nombre',
description: 'Descripción',
amount: 'Cantidad',
actions: 'Comportamiento',
add_category: 'añadir categoría',
new_category: 'Nueva categoría',
category: 'Categoría | Categorias',
select_a_category: 'Seleccione una categoría'
}
},
login: {
email: 'Email',
password: 'Contraseña',
forgot_password: '¿Se te olvidó tu contraseña?',
or_signIn_with: 'o Inicie 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',
login_placeholder: 'mail@example.com'
},
reports: {
title: 'Reporte',
from_date: 'Partir de la fecha',
to_date: 'Hasta la fecha',
status: 'Estado',
paid: 'Pagada',
unpaid: 'No pagado',
download_pdf: 'Descargar PDF',
view_pdf: 'Ver PDF',
update_report: 'Informe de actualización',
report: 'Informe | Informes',
profit_loss: {
profit_loss: 'Pérdida de beneficios',
to_date: 'Hasta la fecha',
from_date: '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',
report_type: 'Tipo de informe'
},
taxes: {
taxes: 'Impuestos',
to_date: 'Hasta la fecha',
from_date: 'Partir de la fecha',
date_range: 'Seleccionar rango de fechas'
},
errors: {
required: 'Se requiere campo'
},
invoices: {
invoice: 'Factura',
invoice_date: 'Fecha de la factura',
due_date: 'Fecha de vencimiento',
amount: 'Cantidad',
contact_name: 'Nombre de contacto',
status: 'Estado'
},
estimates: {
estimate: 'Estimar',
estimate_date: 'Fecha estimada',
due_date: 'Fecha de vencimiento',
estimate_number: 'Numero Estimado',
ref_number: 'Número de referencia',
amount: 'Cantidad',
contact_name: 'Nombre de contacto',
status: 'Estado'
},
expenses: {
expenses: 'Gastos',
category: 'Categoría',
date: 'Fecha',
amount: 'Cantidad',
to_date: 'Hasta la fecha',
from_date: 'Partir de la fecha',
date_range: 'Seleccionar rango de fechas'
}
},
settings: {
menu_title: {
account_settings: 'Configuraciones de la cuenta',
company_information: 'Información de la empresa',
preferences: 'Preferencias',
notifications: 'Notificaciones',
tax_types: 'Tipos de impuestos',
expense_category: 'Categorías de gastos',
update_app: 'Actualizar aplicación'
},
title: 'Configuraciones',
setting: 'Configuraciones | Configuraciones',
general: 'General',
language: 'Idioma',
primary_currency: 'Moneda primaria',
timezone: 'Zona horaria',
date_format: 'Formato de fecha',
currencies: {
title: 'Monedas',
currency: 'Moneda | Monedas',
currencies_list: 'Lista de monedas',
select_currency: 'Seleccione el tipo de moneda',
name: 'Nombre',
code: 'Código',
symbol: 'Símbolo',
precision: 'Precisión',
thousand_separator: 'Mil separadores',
decimal_separator: 'Separador decimal',
position: 'Posición',
position_of_symbol: 'Posición del símbolo',
right: 'Derecho',
left: 'Izquierda',
action: 'Acción',
add_currency: 'Agregar moneda'
},
mail: {
host: 'Host de correo',
port: 'Puerto de correo',
driver: 'Conductor de correo',
secret: 'Secreto',
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',
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.'
},
pdf: {
title: 'Configuración de PDF',
footer_text: 'Texto de pie de página',
pdf_layout: 'Diseño PDF'
},
company_info: {
company_info: 'Información de la compañía',
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.',
phone: 'Teléfono',
country: 'País',
state: 'Estado',
city: 'Ciudad',
address: 'Habla a',
zip: 'Código Postal',
save: 'Salvar',
updated_message: 'Información de la empresa actualizada con éxito'
},
account_settings: {
name: 'Nombre',
email: 'Email',
password: 'Contraseña',
confirm_password: 'Confirmar contraseña',
account_settings: 'Configuraciones de la cuenta',
save: 'Salvar',
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'
},
user_profile: {
name: 'Nombre',
email: 'Email',
password: 'Contraseña',
confirm_password: 'Confirmar contraseña'
},
notification: {
title: 'Notificación',
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',
email_save_message: 'Correo electrónico guardado con éxito',
please_enter_email: 'Por favor, introduzca su correo electrónico'
},
tax_types: {
title: 'Tipos de impuestos',
add_tax: 'Agregar impuesto',
description: 'Puede agregar o eliminar impuestos a su gusto. Crater admite impuestos sobre artículos individuales, así como sobre la factura.',
add_new_tax: 'Agregar nuevo impuesto',
tax_settings: 'Configuraciones de impuestos',
tax_per_item: 'Impuesto por artículo',
tax_name: 'Nombre fiscal',
compound_tax: 'Impuesto compuesto',
percent: 'Por ciento',
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.',
created_message: 'Tipo de impuesto creado con éxito',
updated_message: 'Tipo de impuesto actualizado correctamente',
deleted_message: 'Tipo de impuesto eliminado correctamente',
confirm_delete: 'No podrá recuperar este tipo de impuesto',
already_in_use: 'El impuesto ya está en uso.'
},
expense_category: {
title: 'Categorías de gastos',
action: 'Acción',
description: 'Se requieren categorías para agregar entradas de gastos. Puede Agregar o Eliminar estas categorías según su preferencia.',
add_new_category: 'Añadir nueva categoria',
category_name: 'nombre de la categoría',
category_description: 'Descripción',
created_message: 'Categoría de gastos creada con éxito',
deleted_message: 'Categoría de gastos eliminada correctamente',
updated_message: 'Categoría de gastos actualizada con éxito',
confirm_delete: 'No podrá recuperar esta categoría de gastos',
already_in_use: 'La categoría ya está en uso.'
},
preferences: {
currency: 'Moneda',
language: 'Idioma',
time_zone: 'Zona horaria',
fiscal_year: 'Año financiero',
date_format: 'Formato de fecha',
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',
preference: 'Preferencia | Preferencias',
general_settings: 'Preferencias predeterminadas para el sistema.',
updated_message: 'Preferencias actualizadas exitosamente',
select_language: 'seleccione el idioma',
select_time_zone: 'selecciona la zona horaria',
select_date_formate: 'seleccione formato de fecha',
select_financial_year: 'seleccione año financiero'
},
update_app: {
title: 'Actualizar aplicación',
description: 'actualizar la descripción de la aplicación',
check_update: 'Buscar actualizaciones',
avail_update: 'Nueva actualización disponible',
next_version: 'Próxima versión',
update: 'Actualizar',
update_progress: 'Actualización en progreso...',
progress_text: 'Solo tomará unos minutos. No actualice la pantalla ni cierre la ventana antes de que finalice la actualización.',
update_success: 'La aplicación se actualizó correctamente',
latest_message: '¡Actualización no disponible! Estás en la última versión.',
current_version: 'Versión actual'
}
},
wizard: {
account_info: 'Información de la cuenta',
account_info_desc: 'Los detalles a continuación se utilizarán para crear la cuenta principal de administrador. También puede cambiar los detalles en cualquier momento después de iniciar sesión.',
name: 'Nombre',
email: 'Email',
password: 'Contraseña',
confirm_password: 'Confirmar contraseña',
save_cont: 'Guardar 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',
company_logo: 'Logo de la compañía',
logo_preview: 'Vista previa del logotipo',
preferences: 'Preferencias',
preferences_desc: 'Preferencias predeterminadas para el sistema.',
country: 'País',
state: 'Estado',
city: 'Ciudad',
address: 'Habla a',
street: 'Calle1 ' | 'Calle # 2',
phone: 'Teléfono',
zip_code: 'Código postal',
go_back: 'Regresa',
currency: 'Moneda',
language: 'Idioma',
time_zone: 'Zona horaria',
fiscal_year: 'Año financiero',
date_format: 'Formato de fecha',
from_address: 'De la Dirección',
username: 'Nombre de usuario',
next: 'Próximo',
continue: 'Hacer continuación',
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',
app_url: 'URL de la aplicación',
username: 'Nombre de usuario de la base de datos',
db_name: 'Nombre de la base de datos',
desc: 'Cree una base de datos en su servidor y establezca las credenciales utilizando el siguiente formulario.'
},
permissions: {
permissions: 'Permisos',
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.'
},
mail: {
host: 'Host de correo',
port: 'Puerto de correo',
driver: 'Conductor de correo',
secret: 'Secreto',
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',
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.'
},
req: {
system_req: 'Requisitos del sistema',
php_req_version: 'Php (versión {version} necesario)',
check_req: 'Consultar requisitos',
system_req_desc: 'Crater tiene algunos requisitos de servidor. Asegúrese de que su servidor tenga la versión de php requerida y todas las extensiones mencionadas a continuación.'
},
errors: {
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'
},
success: {
mail_variables_save_successfully: 'Correo electrónico configurado correctamente',
database_variables_save_successfully: 'Base de datos configurada con éxito.'
}
},
layout_login: {
copyright_crater: 'Copyright @ Crater - 2019',
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',
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',
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.',
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.',
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',
amount_maxlength: 'La cantidad no debe ser mayor de 20 dígitos.',
amount_minvalue: 'La cantidad debe ser mayor que 0 dígitos',
description_maxlength: 'La descripción no debe tener más de 255 caracteres.',
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.'
}
}

View File

@ -0,0 +1,811 @@
{
"navigation": {
"dashboard": "Tablero",
"customers": "Clientes",
"items": "Artículos",
"invoices": "Facturas",
"expenses": "Gastos",
"estimates": "Estimadas",
"payments": "Pagos",
"reports": "Informes",
"settings": "Configuraciones",
"logout": "Cerrar sesión"
},
"general": {
"view_pdf": "Ver PDF",
"download_pdf": "Descargar PDF",
"save": "Salvar",
"cancel": "Cancelar",
"update": "Actualizar",
"download": "Descargar",
"from_date": "Partir de 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",
"filter": "Filtrar",
"delete": "Eliminar",
"edit": "Editar",
"view": "Ver",
"add_new_item": "Agregar ítem nuevo",
"clear_all": "Limpiar todo",
"showing": "Demostración",
"of": "de",
"actions": "Comportamiento",
"subtotal": "TOTAL PARCIAL",
"discount": "DESCUENTO",
"fixed": "Fija",
"percentage": "Porcentaje",
"tax": "IMPUESTO",
"total_amount": "CANTIDAD TOTAL",
"bill_to": "Cobrar a",
"ship_to": "Envie a",
"due": "Debida",
"draft": "Sequía",
"sent": "Expedida",
"all": "Todas",
"select_all": "Seleccionar todo",
"choose_file": "Haga clic aquí para elegir un archivo.",
"choose_template": "Elige una plantilla",
"choose": "Escoger",
"remove": "Eliminar",
"powered_by": "Energizado por",
"bytefury": "Bytefury",
"select_a_status": "Selecciona un estado",
"select_a_tax": "Selecciona un impuesto",
"search": "Buscar",
"are_you_sure": "¿Estás seguro?",
"list_is_empty": "La lista esta vacía.",
"no_tax_found": "¡No se encontraron impuestos!",
"four_zero_four": "404",
"you_got_lost": "Whoops! ¡Te perdiste!",
"go_home": "Vete a casa",
"setting_updated": "Configuración actualizada con éxito",
"select_state": "Seleccione estado",
"select_country": "Seleccionar país",
"select_city": "Ciudad selecta",
"street_1": "Calle 1",
"street_2": "Calle # 2",
"action_failed": "Accion: Fallida"
},
"dashboard": {
"select_year": "Seleccione año",
"cards": {
"due_amount": "Monto adeudado",
"customers": "Clientes",
"invoices": "Facturas",
"estimates": "Estimadas"
},
"chart_info": {
"total_sales": "Ventas",
"total_receipts": "Ingresos",
"total_expense": "Gastos",
"net_income": "Lngresos netos",
"year": "Seleccione año"
},
"weekly_invoices": {
"title": "Facturas semanales"
},
"monthly_chart": {
"title": "Gastos de venta"
},
"recent_invoices_card": {
"title": "Facturas adeudadas",
"due_on": "Debido a",
"customer": "Cliente",
"amount_due": "Monto adeudado",
"actions": "Comportamiento",
"view_all": "Ver todo"
},
"recent_estimate_card": {
"title": "Estimaciones recientes",
"date": "Fecha",
"customer": "Cliente",
"amount_due": "Monto adeudado",
"actions": "Comportamiento",
"view_all": "Ver todo"
}
},
"tax_types": {
"name": "Nombre",
"description": "Descripción",
"percent": "Por ciento",
"compound_tax": "Impuesto compuesto"
},
"customers": {
"title": "Clientes",
"add_customer": "Agregar cliente",
"contacts_list": "Lista de clientes",
"name": "Nombre",
"display_name": "Nombre para mostrar",
"primary_contact_name": "Nombre de contacto primario",
"contact_name": "Nombre de contacto",
"amount_due": "Monto adeudado",
"email": "Email",
"address": "Habla a",
"phone": "Teléfono",
"website": "Sitio web",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"zip_code": "Código postal",
"added_on": "Añadido",
"action": "Acción",
"password": "Contraseña",
"street_number": "Número de calle",
"primary_currency": "Moneda primaria",
"add_new_customer": "Agregar nuevo cliente",
"save_customer": "Guardar cliente",
"update_customer": "Actualizar cliente",
"customer": "Cliente | Clientes",
"new_customer": "Nuevo cliente",
"edit_customer": "Editar cliente",
"basic_info": "Información básica",
"billing_address": "Dirección de Envio",
"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!",
"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",
"confirm_delete": "No podrá recuperar este cliente | No podrá recuperar estos clientes",
"created_message": "Cliente creado con éxito",
"updated_message": "Cliente actualizado con éxito",
"deleted_message": "Cliente eliminado correctamente | Clientes eliminados exitosamente"
},
"items": {
"title": "Artículos",
"items_list": "Lista de artículos",
"name": "Nombre",
"unit": "Unidad",
"description": "Descripción",
"added_on": "Añadido",
"price": "Precio",
"date_of_creation": "Fecha de creación",
"action": "Acción",
"add_item": "Añadir artículo",
"save_item": "Guardar artículo",
"update_item": "Actualizar elemento",
"item": "Artículo | Artículos",
"add_new_item": "Agregar ítem nuevo",
"new_item": "Nuevo artículo",
"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",
"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",
"created_message": "Artículo creado con éxito",
"updated_message": "Artículo actualizado con éxito",
"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",
"months": "{meses} Mes",
"years": "{años} Año",
"all": "Todas",
"paid": "Pagada",
"unpaid": "No pagado",
"customer": "CLIENTE",
"ref_no": "NÚMERO DE REFERENCIA.",
"number": "NÚMERO",
"amount_due": "CANTIDAD DEBIDA",
"partially_paid": "Parcialmente pagado",
"total": "Total",
"discount": "Descuento",
"sub_total": "Subtotal",
"estimate_number": "Numero Estimado",
"ref_number": "Número de referencia",
"contact": "Contacto",
"add_item": "Agregar un artículo",
"date": "Fecha",
"due_date": "Fecha de vencimiento",
"expiry_date": "Fecha de caducidad",
"status": "Estado",
"add_tax": "Agregar impuesto",
"amount": "Cantidad",
"action": "Acción",
"notes": "Notas",
"tax": "Impuesto",
"send_estimate": "Enviar presupuesto",
"estimate_template": "Plantilla de estimación",
"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?",
"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",
"errors": {
"required": "Se requiere campo"
},
"accepted": "Aceptada",
"sent": "Expedida",
"draft": "Sequía",
"declined": "Rechazada",
"new_estimate": "Nueva estimación",
"add_new_estimate": "Añadir nuevo presupuesto",
"update_Estimate": "Actualizar presupuesto",
"edit_estimate": "Editar estimación",
"items": "artículos",
"Estimate": "Estimación | Estimados",
"add_new_tax": "Agregar nuevo impuesto",
"no_estimates": "¡Aún no hay estimaciones!",
"list_of_estimates": "Esta sección contendrá la lista de estimaciones.",
"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",
"item": {
"title": "Título del artículo",
"description": "Descripción",
"quantity": "Quantity",
"price": "Precio",
"discount": "Descuento",
"total": "Total",
"total_discount": "Descuento total",
"sub_total": "Subtotal",
"tax": "Impuesto",
"amount": "Cantidad",
"select_an_item": "Escriba o haga clic para seleccionar un elemento",
"type_item_description": "Tipo Elemento Descripción (opcional)"
}
},
"invoices": {
"title": "Facturas",
"invoices_list": "Lista de facturas",
"days": "{días} días",
"months": "{meses} Mes",
"years": "{años} Año",
"all": "Todas",
"paid": "Pagada",
"unpaid": "No pagado",
"customer": "CLIENTE",
"paid_status": "ESTADO PAGADO",
"ref_no": "NÚMERO DE REFERENCIA.",
"number": "NÚMERO",
"amount_due": "CANTIDAD DEBIDA",
"partially_paid": "Parcialmente pagado",
"total": "Total",
"discount": "Descuento",
"sub_total": "Subtotal",
"invoice": "Factura | Facturas",
"invoice_number": "Numero de factura",
"ref_number": "Número de referencia",
"contact": "Contacto",
"add_item": "Agregar un artículo",
"date": "Fecha",
"due_date": "Fecha de vencimiento",
"status": "Estado",
"add_tax": "Agregar impuesto",
"amount": "Cantidad",
"action": "Acción",
"notes": "Notas",
"view": "Ver",
"send_invoice": "Enviará la factura",
"invoice_template": "Plantilla de factura",
"template": "Modelo",
"mark_as_sent": "Marcar como enviado",
"invoice_mark_as_sent": "Esta factura se marcará como enviada",
"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",
"edit_invoice": "Editar factura",
"new_invoice": "Nueva factura",
"save_invoice": "Guardar factura",
"update_invoice": "Actualizar factura",
"add_new_tax": "Agregar nuevo impuesto",
"no_invoices": "¡Aún no hay facturas!",
"list_of_invoices": "Esta sección contendrá la lista de facturas.",
"select_invoice": "Seleccionar factura",
"mark_as_sent_successfully": "Factura marcada como enviada con éxito",
"send_invoice_successfully": "Factura enviada exitosamente",
"item": {
"title": "Título del artículo",
"description": "Descripción",
"quantity": "Cantidad",
"price": "Precio",
"discount": "Descuento",
"total": "Total",
"total_discount": "Descuento total",
"sub_total": "Subtotal",
"tax": "Impuesto",
"amount": "Cantidad",
"select_an_item": "Escriba o haga clic para seleccionar un elemento",
"type_item_description": "Tipo Elemento Descripción (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",
"created_message": "Factura creada exitosamente",
"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"
},
"credit_notes": {
"title": "Notas de credito",
"credit_notes_list": "Lista de notas de crédito",
"credit_notes": "Notas de credito",
"contact": "Contacto",
"date": "Fecha",
"amount": "Cantidad",
"action": "Acción",
"credit_number": "Número de crédito",
"notes": "Notas",
"confirm_delete": "¿Desea eliminar esta nota de crédito?",
"item": {
"title": "Título del artículo",
"description": "Descripción",
"quantity": "Cantidad",
"price": "Precio",
"discount": "Descuento",
"total": "Total",
"total_discount": "Descuento total",
"sub_total": "Subtotal",
"tax": "Impuesto"
}
},
"payments": {
"title": "Pagos",
"payments_list": "Lista de pagos",
"record_payment": "Registro de pago",
"customer": "Cliente",
"date": "Fecha",
"amount": "Cantidad",
"action": "Acción",
"payment_number": "Numero de pago",
"payment_mode": "Modo de pago",
"invoice": "Factura",
"note": "Nota",
"add_payment": "Agregar pago",
"new_payment": "Nuevo pago",
"edit_payment": "Editar pago",
"view_payment": "Ver pago",
"add_new_payment": "Agregar nuevo pago",
"save_payment": "Guardar pago",
"update_payment": "Actualizar pago",
"payment": "Pago | Pagos",
"no_payments": "¡Aún no hay pagos!",
"list_of_payments": "Esta sección contendrá la lista de pagos.",
"select_payment_mode": "Seleccionar modo de pago",
"confirm_delete": "No podrá recuperar este pago | No podrá recuperar estos pagos",
"created_message": "Pago creado con éxito",
"updated_message": "Pago actualizado con éxito",
"deleted_message": "Pago eliminado con éxito | Pagos eliminados exitosamente",
"invalid_amount_message": "El importe del pago no es válido."
},
"expenses": {
"title": "Gastos",
"expenses_list": "Lista de gastos",
"expense_title": "Título",
"contact": "Contacto",
"category": "Categoría",
"from_date": "Partir de la fecha",
"to_date": "Hasta la fecha",
"expense_date": "Fecha",
"description": "Descripción",
"receipt": "Recibo",
"amount": "Cantidad",
"action": "Acción",
"note": "Nota",
"category_id": "Categoria ID",
"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",
"download_receipt": "Descargar recibo",
"edit_expense": "Editar gasto",
"new_expense": "Nuevo gasto",
"expense": "Gastos | Gastos",
"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",
"created_message": "Gastos creados exitosamente",
"updated_message": "Gastos actualizados con éxito",
"deleted_message": "Gastos eliminados con éxito | Gastos eliminados exitosamente",
"categories": {
"categories_list": "Lista de categorías",
"title": "Título",
"name": "Nombre",
"description": "Descripción",
"amount": "Cantidad",
"actions": "Comportamiento",
"add_category": "añadir categoría",
"new_category": "Nueva categoría",
"category": "Categoría | Categorias",
"select_a_category": "Seleccione una categoría"
}
},
"login": {
"email": "Email",
"password": "Contraseña",
"forgot_password": "¿Se te olvidó tu contraseña?",
"or_signIn_with": "o Inicie 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",
"login_placeholder": "mail@example.com"
},
"reports": {
"title": "Reporte",
"from_date": "Partir de la fecha",
"to_date": "Hasta la fecha",
"status": "Estado",
"paid": "Pagada",
"unpaid": "No pagado",
"download_pdf": "Descargar PDF",
"view_pdf": "Ver PDF",
"update_report": "Informe de actualización",
"report": "Informe | Informes",
"profit_loss": {
"profit_loss": "Pérdida de beneficios",
"to_date": "Hasta la fecha",
"from_date": "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",
"report_type": "Tipo de informe"
},
"taxes": {
"taxes": "Impuestos",
"to_date": "Hasta la fecha",
"from_date": "Partir de la fecha",
"date_range": "Seleccionar rango de fechas"
},
"errors": {
"required": "Se requiere campo"
},
"invoices": {
"invoice": "Factura",
"invoice_date": "Fecha de la factura",
"due_date": "Fecha de vencimiento",
"amount": "Cantidad",
"contact_name": "Nombre de contacto",
"status": "Estado"
},
"estimates": {
"estimate": "Estimar",
"estimate_date": "Fecha estimada",
"due_date": "Fecha de vencimiento",
"estimate_number": "Numero Estimado",
"ref_number": "Número de referencia",
"amount": "Cantidad",
"contact_name": "Nombre de contacto",
"status": "Estado"
},
"expenses": {
"expenses": "Gastos",
"category": "Categoría",
"date": "Fecha",
"amount": "Cantidad",
"to_date": "Hasta la fecha",
"from_date": "Partir de la fecha",
"date_range": "Seleccionar rango de fechas"
}
},
"settings": {
"menu_title": {
"account_settings": "Configuraciones de la cuenta",
"company_information": "Información de la empresa",
"preferences": "Preferencias",
"notifications": "Notificaciones",
"tax_types": "Tipos de impuestos",
"expense_category": "Categorías de gastos",
"update_app": "Actualizar aplicación"
},
"title": "Configuraciones",
"setting": "Configuraciones | Configuraciones",
"general": "General",
"language": "Idioma",
"primary_currency": "Moneda primaria",
"timezone": "Zona horaria",
"date_format": "Formato de fecha",
"currencies": {
"title": "Monedas",
"currency": "Moneda | Monedas",
"currencies_list": "Lista de monedas",
"select_currency": "Seleccione el tipo de moneda",
"name": "Nombre",
"code": "Código",
"symbol": "Símbolo",
"precision": "Precisión",
"thousand_separator": "Mil separadores",
"decimal_separator": "Separador decimal",
"position": "Posición",
"position_of_symbol": "Posición del símbolo",
"right": "Derecho",
"left": "Izquierda",
"action": "Acción",
"add_currency": "Agregar moneda"
},
"mail": {
"host": "Host de correo",
"port": "Puerto de correo",
"driver": "Conductor de correo",
"secret": "Secreto",
"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",
"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."
},
"pdf": {
"title": "Configuración de PDF",
"footer_text": "Texto de pie de página",
"pdf_layout": "Diseño PDF"
},
"company_info": {
"company_info": "Información de la compañía",
"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.",
"phone": "Teléfono",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"address": "Habla a",
"zip": "Código Postal",
"save": "Salvar",
"updated_message": "Información de la empresa actualizada con éxito"
},
"account_settings": {
"profile_picture": "Foto de perfil",
"name": "Nombre",
"email": "Email",
"password": "Contraseña",
"confirm_password": "Confirmar contraseña",
"account_settings": "Configuraciones de la cuenta",
"save": "Salvar",
"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"
},
"user_profile": {
"name": "Nombre",
"email": "Email",
"password": "Contraseña",
"confirm_password": "Confirmar contraseña"
},
"notification": {
"title": "Notificación",
"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",
"email_save_message": "Correo electrónico guardado con éxito",
"please_enter_email": "Por favor, introduzca su correo electrónico"
},
"tax_types": {
"title": "Tipos de impuestos",
"add_tax": "Agregar impuesto",
"description": "Puede agregar o eliminar impuestos a su gusto. Crater admite impuestos sobre artículos individuales, así como sobre la factura.",
"add_new_tax": "Agregar nuevo impuesto",
"tax_settings": "Configuraciones de impuestos",
"tax_per_item": "Impuesto por artículo",
"tax_name": "Nombre fiscal",
"compound_tax": "Impuesto compuesto",
"percent": "Por ciento",
"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.",
"created_message": "Tipo de impuesto creado con éxito",
"updated_message": "Tipo de impuesto actualizado correctamente",
"deleted_message": "Tipo de impuesto eliminado correctamente",
"confirm_delete": "No podrá recuperar este tipo de impuesto",
"already_in_use": "El impuesto ya está en uso."
},
"expense_category": {
"title": "Categorías de gastos",
"action": "Acción",
"description": "Se requieren categorías para agregar entradas de gastos. Puede Agregar o Eliminar estas categorías según su preferencia.",
"add_new_category": "Añadir nueva categoria",
"category_name": "nombre de la categoría",
"category_description": "Descripción",
"created_message": "Categoría de gastos creada con éxito",
"deleted_message": "Categoría de gastos eliminada correctamente",
"updated_message": "Categoría de gastos actualizada con éxito",
"confirm_delete": "No podrá recuperar esta categoría de gastos",
"already_in_use": "La categoría ya está en uso."
},
"preferences": {
"currency": "Moneda",
"language": "Idioma",
"time_zone": "Zona horaria",
"fiscal_year": "Año financiero",
"date_format": "Formato de fecha",
"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",
"preference": "Preferencia | Preferencias",
"general_settings": "Preferencias predeterminadas para el sistema.",
"updated_message": "Preferencias actualizadas exitosamente",
"select_language": "seleccione el idioma",
"select_time_zone": "selecciona la zona horaria",
"select_date_formate": "seleccione formato de fecha",
"select_financial_year": "seleccione año financiero"
},
"update_app": {
"title": "Actualizar aplicación",
"description": "actualizar la descripción de la aplicación",
"check_update": "Buscar actualizaciones",
"avail_update": "Nueva actualización disponible",
"next_version": "Próxima versión",
"update": "Actualizar",
"update_progress": "Actualización en progreso...",
"progress_text": "Solo tomará unos minutos. No actualice la pantalla ni cierre la ventana antes de que finalice la actualización.",
"update_success": "¡La aplicación ha sido actualizada! Espere mientras la ventana de su navegador se vuelve a cargar automáticamente.",
"latest_message": "¡Actualización no disponible! Estás en la última versión.",
"current_version": "Versión actual"
}
},
"wizard": {
"account_info": "Información de la cuenta",
"account_info_desc": "Los detalles a continuación se utilizarán para crear la cuenta principal de administrador. También puede cambiar los detalles en cualquier momento después de iniciar sesión.",
"name": "Nombre",
"email": "Email",
"password": "Contraseña",
"confirm_password": "Confirmar contraseña",
"save_cont": "Guardar 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",
"company_logo": "Logo de la compañía",
"logo_preview": "Vista previa del logotipo",
"preferences": "Preferencias",
"preferences_desc": "Preferencias predeterminadas para el sistema.",
"country": "País",
"state": "Estado",
"city": "Ciudad",
"address": "Habla a",
"street": "Calle1 | Calle # 2",
"phone": "Teléfono",
"zip_code": "Código postal",
"go_back": "Regresa",
"currency": "Moneda",
"language": "Idioma",
"time_zone": "Zona horaria",
"fiscal_year": "Año financiero",
"date_format": "Formato de fecha",
"from_address": "De la Dirección",
"username": "Nombre de usuario",
"next": "Próximo",
"continue": "Hacer continuación",
"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",
"app_url": "URL de la aplicación",
"username": "Nombre de usuario de la base de datos",
"db_name": "Nombre de la base de datos",
"desc": "Cree una base de datos en su servidor y establezca las credenciales utilizando el siguiente formulario."
},
"permissions": {
"permissions": "Permisos",
"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."
},
"mail": {
"host": "Host de correo",
"port": "Puerto de correo",
"driver": "Conductor de correo",
"secret": "Secreto",
"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",
"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."
},
"req": {
"system_req": "Requisitos del sistema",
"php_req_version": "Php (versión {version} necesario)",
"check_req": "Consultar requisitos",
"system_req_desc": "Crater tiene algunos requisitos de servidor. Asegúrese de que su servidor tenga la versión de php requerida y todas las extensiones mencionadas a continuación."
},
"errors": {
"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"
},
"success": {
"mail_variables_save_successfully": "Correo electrónico configurado correctamente",
"database_variables_save_successfully": "Base de datos configurada con éxito."
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2019",
"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",
"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",
"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.",
"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.",
"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",
"amount_maxlength": "La cantidad no debe ser mayor de 20 dígitos.",
"amount_minvalue": "La cantidad debe ser mayor que 0 dígitos",
"description_maxlength": "La descripción no debe tener más de 255 caracteres.",
"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."
}
}

View File

@ -1,815 +0,0 @@
export default {
navigation: {
// key : 'singular | plural'
dashboard: 'Tableau de bord',
customers: 'Cliente',
items: 'Articles',
invoices: 'Factures',
expenses: 'Les dépenses',
estimates: 'Estimations',
payments: 'Paiements',
reports: 'Rapports',
settings: 'Paramètres',
logout: 'Se déconnecter'
},
general: {
view_pdf: 'Voir PDF',
download_pdf: 'Télécharger le PDF',
save: 'sauver',
cancel: 'Annuler',
update: 'Mise à jour',
download: 'Télécharger',
from_date: 'Partir de la date',
to_date: 'À ce jour',
from: 'De',
to: 'À',
go_back: 'Retourner',
back_to_login: 'Retour connexion?',
home: 'Accueil',
filter: 'Filtre',
delete: 'Effacer',
edit: 'Modifier',
view: 'Vue',
add_new_item: 'Ajoute un nouvel objet',
clear_all: 'Tout effacer',
showing: 'Montrant',
of: 'de',
actions: 'Actions',
subtotal: 'TOTAL',
discount: 'REMISE',
fixed: 'Fixée',
percentage: 'Pourcentage',
tax: 'IMPÔT',
total_amount: 'MONTANT TOTAL',
bill_to: 'facturer',
ship_to: 'Envoyez à',
due: 'Dû',
draft: 'Brouillon',
sent: 'Envoyée',
all: 'Tout',
select_all: 'Tout sélectionner',
choose_file: 'Cliquez ici pour choisir un fichier',
choose_template: 'Choisissez un modèle',
choose: 'Choisir',
remove: 'Retirer',
powered_by: 'Alimenté 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?',
list_is_empty: 'La liste est vide',
no_tax_found: 'Aucune taxe trouvée!',
four_zero_four: '404',
you_got_lost: 'Oups! Vous vous êtes perdus!',
go_home: 'Rentrer chez soi',
setting_updated: 'Réglage mis à jour avec succès',
select_state: "Sélectionnez l'état",
select_country: 'Choisissez le pays',
select_city: 'Sélectionnez une ville',
street_1: 'Rue 1',
street_2: 'Rue # 2',
action_failed: 'Action: échoué'
},
dashboard: {
select_year: 'Sélectionnez lannée',
cards: {
due_amount: 'Montant dû',
customers: 'Les clients',
invoices: 'Factures',
estimates: 'Estimations'
},
chart_info: {
total_sales: 'Ventes',
total_receipts: 'Reçus',
total_expense: 'Les dépenses',
net_income: 'Revenu net',
year: 'Sélectionnez lannée'
},
weekly_invoices: {
title: 'Factures hebdomadaires'
},
monthly_chart: {
title: 'Ventes et dépenses'
},
recent_invoices_card: {
title: 'Factures dues',
due_on: 'Due On',
customer: 'Cliente',
amount_due: 'Montant dû',
actions: 'Actions',
view_all: 'Voir tout'
},
recent_estimate_card: {
title: 'Estimations récentes',
date: 'Date',
customer: 'Cliente',
amount_due: 'Montant dû',
actions: 'Actions',
view_all: 'Voir tout'
}
},
tax_types: {
name: 'Nom',
description: 'La description',
percent: 'Pour cent',
compound_tax: 'Taxe composée'
},
customers: {
title: 'Les 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',
contact_name: 'Nom du contact',
amount_due: 'Montant dû',
email: 'Email',
address: 'Adresse',
phone: 'Téléphone',
website: 'Site Internet',
country: 'Pays',
state: 'Etat',
city: 'Ville',
zip_code: 'Code postal',
added_on: 'Ajouté le',
action: 'action',
password: 'Mot de passe',
street_number: 'Numéro de rue',
primary_currency: 'Devise principale',
add_new_customer: 'Ajouter un nouveau client',
save_customer: 'Enregistrer le client',
update_customer: 'Mettre à jour le client',
customer: 'Client | Les clients',
new_customer: 'Nouveau client',
edit_customer: 'Modifier le client',
basic_info: 'Informations de base',
billing_address: 'Adresse de facturation',
shipping_address: 'Adresse de livraison',
copy_billing_address: 'Copier de la facturation',
no_customers: 'Pas encore de clients!',
no_customers_found: 'Aucun client trouvé!',
list_of_customers: 'Cette section contiendra la liste des clients.',
primary_display_name: 'Nom daffichage principal',
select_state: 'Sélectionnez létat',
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',
select_a_customer: 'Sélectionnez un client',
type_or_click: 'Tapez ou cliquez pour sélectionner',
confirm_delete: 'Vous ne pourrez pas récupérer ce client | Vous ne pourrez pas récupérer ces clients',
created_message: 'Client créé avec succès',
updated_message: 'Client mis à jour avec succès',
deleted_message: 'Client supprimé avec succès | Les clients supprimés avec succès'
},
items: {
title: 'Articles',
items_list: 'Liste darticles',
name: 'Nom',
unit: 'Unité',
description: 'La description',
added_on: 'Ajouté le',
price: 'Prix',
date_of_creation: 'Date de création',
action: 'action',
add_item: 'Ajouter un item',
save_item: 'Enregistrer lélément',
update_item: 'Mettre à jour lélément',
item: 'Article | Articles',
add_new_item: 'Ajoute un nouvel objet',
new_item: 'Nouvel article',
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é',
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',
created_message: 'Article créé avec succès',
updated_message: 'Élément mis à jour avec succès',
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',
days: '{jours} jours',
months: '{mois} mois',
years: '{années} Année',
all: 'Toute',
paid: 'Payé',
unpaid: 'Non payé',
customer: 'CLIENTE CLIENT',
ref_no: 'REF NO.',
number: 'NOMBRE',
amount_due: 'MONTANT DÛ',
partially_paid: 'Partiellement payé',
total: 'Totale',
discount: 'Remise',
sub_total: 'Total partiel',
estimate_number: 'Numéro destimation',
ref_number: 'Numéro de ref',
contact: 'Contact',
add_item: 'Ajouter un article',
date: 'Date',
due_date: 'Date déchéance',
expiry_date: 'Date dexpiration',
status: 'Statut',
add_tax: 'Ajouter une taxe',
amount: 'Montante',
action: 'action',
notes: 'Remarques',
tax: 'Impôt',
estimate_template: 'Modèle destimation',
convert_to_invoice: 'Convertir en facture',
mark_as_sent: 'Marquer comme envoyé',
send_estimate: 'Envoyer une estimation',
record_payment: 'Record de paiement',
add_estimate: 'Ajouter une estimation',
save_estimate: 'Sauvegarder lestimation',
confirm_conversion: 'Vous souhaitez convertir cette estimation 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',
errors: {
required: 'Champ requis'
},
accepted: 'Accepté',
sent: 'Envoyée',
draft: 'Brouillon',
declined: 'Diminué',
new_estimate: 'Nouvelle estimation',
add_new_estimate: 'Ajouter une nouvelle estimation',
update_Estimate: 'Mise à jour de lestimation',
edit_estimate: 'Modifier lestimation',
items: 'articles',
Estimate: 'Estimation | Estimations',
add_new_tax: 'Ajouter une nouvelle taxe',
no_estimates: 'Aucune estimation pour le moment!',
list_of_estimates: 'Cette section contiendra la liste des estimations.',
mark_as_rejected: 'Marquer comme rejeté',
mark_as_accepted: 'Marquer comme accepté',
marked_as_accepted_message: 'Estimation marquée comme acceptée',
marked_as_rejected_message: 'Estimation marquée comme rejetée',
confirm_delete: 'Vous ne pourrez pas récupérer cette estimation | Vous ne pourrez pas récupérer ces estimations',
created_message: 'Estimation créée avec succès',
updated_message: 'Estimation mise à jour avec succès',
deleted_message: 'Estimation supprimée avec succès | Estimations supprimées avec succès',
item: {
title: 'Titre de larticle',
description: 'La description',
quantity: 'Quantité',
price: 'Prix',
discount: 'Remise',
total: 'Totale',
total_discount: 'Remise totale',
sub_total: 'Total partiel',
tax: 'Impôt',
amount: 'Montante',
select_an_item: 'Tapez ou cliquez pour sélectionner un élément',
type_item_description: 'Type Item Description (optionnel)'
}
},
invoices: {
title: 'Factures',
invoices_list: 'Liste de factures',
days: '{jours} jours',
months: '{mois} mois',
years: '{années} Année',
all: 'Toute',
paid: 'Payé',
unpaid: 'Non payé',
customer: 'CLIENTE CLIENT',
paid_status: 'Statut payé',
ref_no: 'REF NO.',
number: 'NOMBRE',
amount_due: 'MONTANT DÛ',
partially_paid: 'Partiellement payé',
total: 'Totale Total',
discount: 'Remise',
sub_total: 'Total partiel',
invoice: 'Facture | Factures',
invoice_number: 'Numéro de facture',
ref_number: 'Numéro de ref',
contact: 'Contact',
add_item: 'Ajouter un article',
date: 'Date',
due_date: 'Date déchéance',
status: 'Statut',
add_tax: 'Ajouter une taxe',
amount: 'Montante Montant',
action: 'action',
notes: 'Remarques',
view: 'Vue',
send_invoice: 'Envoyer une facture',
invoice_template: 'Modèle de facture',
template: 'Modèle',
mark_as_sent: 'Marquer comme envoyé',
invoice_mark_as_sent: 'Cette facture sera marquée comme envoyé',
confirm_send: 'Cette facture sera envoyée par courrier électronique au client.',
invoice_date: 'Date de facturation',
record_payment: 'Record de paiement',
add_new_invoice: 'Ajouter une nouvelle facture',
update_expense: 'Frais de mise à jour',
edit_invoice: 'Modifier la facture',
new_invoice: 'Nouvelle facture',
save_invoice: 'Enregistrer la facture',
update_invoice: 'Mettre à jour la facture',
add_new_tax: 'Ajouter une nouvelle taxe',
no_invoices: 'Aucune facture pour le moment!',
list_of_invoices: 'Cette section contiendra la liste des factures.',
select_invoice: 'Sélectionnez facture',
mark_as_sent_successfully: 'Facture marquée comme envoyée avec succès',
send_invoice_successfully: 'Facture envoyée avec succès',
item: {
title: 'Titre de larticle',
description: 'La description',
quantity: 'Quantité',
price: 'Prix',
discount: 'Remise',
total: 'Totale Total',
total_discount: 'Remise totale',
sub_total: 'Total partiel',
tax: 'Impôt',
amount: 'Montante Montant',
select_an_item: 'Tapez ou cliquez pour sélectionner un élément',
type_item_description: 'Type Item Description (optionnel)'
},
payment_attached_message: "Un paiement est déjà associé à l'une des factures sélectionnées. Assurez-vous deffacer dabord les paiements en pièce jointe afin de procéder à la suppression.",
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',
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'
},
credit_notes: {
title: 'Notes de crédit',
credit_notes_list: 'Liste des notes de crédit',
// Fields
credit_notes: 'Notes de crédit',
contact: 'Contact',
date: 'Date',
amount: 'Montante Montant',
action: 'action',
credit_number: 'Numéro de crédit',
notes: 'Remarques',
confirm_delete: 'Voulez-vous supprimer cet avoir?',
item: {
title: 'Titre de larticle',
description: 'La description',
quantity: 'Quantité',
price: 'Prix',
discount: 'Remise',
total: 'Totale Total',
total_discount: 'Remise totale',
sub_total: 'Total partiel',
tax: 'Impôt'
}
},
payments: {
title: 'Paiements',
payments_list: 'Liste de paiements',
record_payment: 'Record de paiement',
// Fields
customer: 'Cliente Client',
date: 'Date',
amount: 'Montante Montant',
action: 'action',
payment_number: 'Numéro de paiement',
payment_mode: 'Mode de paiement',
invoice: 'Facture dachat',
note: 'Remarque',
add_payment: 'Ajouter un paiement',
new_payment: 'Nouveau paiement',
edit_payment: 'Modifier le paiement',
view_payment: 'Voir le paiement',
add_new_payment: 'Ajouter un nouveau paiement',
save_payment: 'Enregistrer le paiement',
update_payment: 'Mettre à jour le paiement',
payment: 'Paiement | Paiements',
no_payments: 'Aucun paiement pour le moment!',
list_of_payments: 'Cette section contiendra la liste des paiements',
select_payment_mode: 'Sélectionnez le mode de paiement',
confirm_delete: 'Vous ne pourrez pas récupérer ce paiement | Vous ne pourrez pas récupérer ces paiements',
created_message: 'Paiement créé avec succès',
updated_message: 'Paiement mis à jour avec succès',
deleted_message: 'Paiement supprimé avec succès | Paiements supprimés avec succès',
invalid_amount_message: 'Le montant du paiement est invalide'
},
expenses: {
title: 'Les dépenses',
expenses_list: 'Liste des dépenses',
// Fields
expense_title: 'Titre',
contact: 'Contact',
category: 'Catégorie',
from_date: 'Partir de la date',
to_date: 'À ce jour',
expense_date: 'Date',
description: 'La description',
receipt: 'Le reçu',
amount: 'Montante Montant',
action: 'action',
note: 'Remarque',
category_id: 'Identifiant de catégorie',
date: 'Date de dépense',
add_expense: 'Ajouter une dépense',
add_new_expense: 'Ajouter une nouvelle dépense',
save_expense: 'Économiser des dépenses',
update_expense: 'Frais de mise à jour',
download_receipt: 'Télécharger le reçu',
edit_expense: 'Modifier les dépenses',
new_expense: 'Nouvelle dépense',
expense: 'Frais | Les dépenses',
no_expenses: 'Pas de dépenses pour le moment!',
list_of_expenses: 'Cette section contiendra la liste des dépenses.',
confirm_delete: 'Vous ne pourrez pas récupérer cette dépense | Vous ne pourrez pas récupérer ces frais',
created_message: 'Dépense créée avec succès',
updated_message: 'Dépense mise à jour avec succès',
deleted_message: 'Dépense supprimée avec succès | Dépenses supprimées avec succès',
categories: {
categories_list: 'Liste des catégories',
title: 'Titre',
name: 'Nom',
description: 'La description',
amount: 'Montante Montant',
actions: 'Actions',
add_category: 'ajouter une catégorie',
new_category: 'Nouvelle catégorie',
category: 'Catégorie | Les catégories',
select_a_category: 'choisissez une catégorie'
}
},
login: {
email: 'Email',
password: 'Mot de passe',
forgot_password: 'Mot de passe oublié?',
or_signIn_with: 'ou Connectez-vous avec:',
login: 'Sidentifier',
register: 'Sinscrire',
reset_password: 'réinitialiser le mot de passe',
enter_email: 'Entrer email',
enter_password: 'Entrer le mot de passe',
retype_password: 'Retaper le mot de passe',
login_placeholder: 'mail@example.com'
},
reports: {
title: 'rapport',
from_date: 'Partir de la date',
to_date: 'À ce jour',
status: 'Statut',
paid: 'Payé',
unpaid: 'Non payé',
download_pdf: 'Télécharger le PDF',
view_pdf: 'Voir PDF',
update_report: 'Rapport de mise à jour',
report: 'Rapport | Rapports',
profit_loss: {
profit_loss: 'Perte de profit',
to_date: 'À ce jour',
from_date: 'Partir de la date',
date_range: 'Sélectionner une plage de dates'
},
sales: {
sales: 'Ventes',
date_range: 'Sélectionner une plage de dates',
to_date: 'À ce jour',
from_date: 'Partir de la date',
report_type: 'Type de rapport'
},
taxes: {
taxes: 'Les taxes',
to_date: 'À ce jour',
from_date: 'Partir de la date',
date_range: 'Sélectionner une plage de dates'
},
errors: {
required: 'Champ requis'
},
invoices: {
invoice: 'Facture dachat',
invoice_date: 'Date de facturation',
due_date: 'Date déchéance',
amount: 'Montante ',
contact_name: 'Nom du contact',
status: 'Statut'
},
estimates: {
estimate: 'Estimation',
estimate_date: 'Date destimation',
due_date: 'Date déchéance',
estimate_number: 'Numéro destimation',
ref_number: 'Numéro de ref',
amount: 'Montante',
contact_name: 'Nom du contact',
status: 'Statut'
},
expenses: {
expenses: 'Les dépenses',
category: 'Catégorie',
date: 'Date',
amount: 'Montante',
to_date: 'À ce jour',
from_date: 'Partir de la date',
date_range: 'Sélectionner une plage de dates'
}
},
settings: {
menu_title: {
account_settings: 'Paramètres du compte',
company_information: 'Informations sur la société',
preferences: 'Préférences',
notifications: 'Les notifications',
tax_types: 'Types de taxe',
expense_category: 'Catégories de dépenses',
update_app: "Mise à jour de l'application"
},
title: 'Paramètres',
setting: 'Paramètres | Paramètres',
general: 'Générale',
language: 'La langue',
primary_currency: 'Devise principale',
timezone: 'Fuseau horaire',
date_format: 'Format de date',
currencies: {
title: 'Monnaies',
currency: 'Monnaie | Monnaies',
currencies_list: 'Liste des devises',
select_currency: 'Sélectionnez la devise',
name: 'Nom',
code: 'Code',
symbol: 'symbole',
precision: 'Précision',
thousand_separator: 'Mille séparateur',
decimal_separator: 'Séparateur décimal',
position: 'Position',
position_of_symbol: 'Position du symbole',
right: 'Droite',
left: 'La gauche',
action: 'action',
add_currency: 'Ajouter une devise'
},
mail: {
host: 'Mail Host',
port: 'Port mail',
driver: 'Pilote de courrier',
password: 'Mot de passe 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',
username: "Mail Nom d'utilisateur",
mail_config: 'Configuration du courrier',
encryption: 'Chiffrement du courrier',
mail_config_desc: "Les détails ci-dessous seront utilisés pour mettre à jour l'environnement de messagerie. Aussi, vous pouvez modifier les détails à tout moment après la connexion."
},
pdf: {
title: 'Paramètre PDF',
footer_text: 'Pied de page texte',
pdf_layout: 'Mise en page PDF'
},
company_info: {
company_info: 'Information dentreprise',
company_name: 'Nom de la compagnie',
company_logo: 'Logo dentreprise',
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',
state: 'Etat',
city: 'Ville',
address: 'Adresse',
zip: 'Zip *: français',
save: 'sauver',
updated_message: 'Informations sur la société mises à jour avec succès'
},
account_settings: {
name: 'Nom',
email: 'Email',
password: 'Mot de passe',
confirm_password: 'Confirmez le mot de passe',
account_settings: 'Paramètres du compte',
save: 'sauver',
section_description: 'Vous pouvez mettre à jour votre nom, votre email et votre mot de passe en utilisant le formulaire ci-dessous.',
updated_message: 'Paramètres du compte mis à jour avec succès'
},
user_profile: {
name: 'Nom',
email: 'Email',
password: 'Mot de passe',
confirm_password: 'Confirmez le mot de passe'
},
notification: {
title: 'Notification',
email: 'Envoyer des notifications à',
description: 'Quelles notifications par courrier électronique souhaitez-vous recevoir lorsque quelque chose change?',
invoice_viewed: 'Facture consultée',
invoice_viewed_desc: 'Lorsque votre client visualise la facture envoyée via le tableau de bord du cratère.',
estimate_viewed: 'Estimation vue',
estimate_viewed_desc: 'Lorsque votre client visualise le devis envoyé via le tableau de bord du cratère.',
save: 'sauver',
email_save_message: 'Email enregistré avec succès',
invoice_viewed_message: 'Facture consultée',
estimate_viewed_message: 'Estimation vue',
please_enter_email: 'S il vous plaît entrer email'
},
tax_types: {
title: 'Types de taxe',
add_tax: 'Ajouter une taxe',
description: 'Vous pouvez ajouter ou supprimer des taxes à votre guise. Crater prend en charge les taxes sur les articles individuels ainsi que sur la facture.',
add_new_tax: 'Ajouter une nouvelle taxe',
tax_settings: 'Paramètres de taxe',
tax_per_item: 'Taxe par article',
tax_name: 'Nom de la taxe',
compound_tax: 'Taxe composée',
percent: 'Pour cent',
action: 'action',
tax_setting_description: 'Activez cette option si vous souhaitez ajouter des taxes à des postes de facture individuels. Par défaut, les taxes sont ajoutées directement à la facture.',
created_message: 'Type de taxe créé avec succès',
updated_message: 'Type de taxe mis à jour avec succès',
deleted_message: 'Type de taxe supprimé avec succès',
confirm_delete: 'Vous ne pourrez pas récupérer ce type de taxe',
already_in_use: 'La taxe est déjà utilisée'
},
expense_category: {
title: 'Catégories de dépenses',
action: 'action',
description: 'Des catégories sont requises pour ajouter des entrées de dépenses. Vous pouvez ajouter ou supprimer ces catégories selon vos préférences.',
add_new_category: 'Ajouter une nouvelle catégorie',
category_name: 'Nom de catégorie',
category_description: 'La description',
created_message: 'Catégorie de dépenses créée avec succès',
deleted_message: 'La catégorie de dépenses a été supprimée avec succès',
updated_message: 'Catégorie de dépenses mise à jour avec succès',
confirm_delete: 'Vous ne pourrez pas récupérer cette catégorie de dépenses',
already_in_use: 'La catégorie est déjà utilisée'
},
preferences: {
currency: 'Devise',
language: 'La langue',
time_zone: 'Fuseau horaire',
fiscal_year: 'Année financière',
date_format: 'Format de date',
discount_setting: 'Réglage de remise',
discount_per_item: 'Remise par article',
discount_setting_description: 'Activez cette option si vous souhaitez ajouter une remise à des postes de facture individuels. Par défaut, les remises sont ajoutées directement à la facture.',
save: 'sauver',
preference: 'Préférence | Préférences',
general_settings: 'Préférences par défaut pour le système.',
updated_message: 'Préférences mises à jour avec succès',
set_discount_per_item_message: 'Jeu de remise par article',
select_language: 'Choisir la langue',
select_time_zone: 'sélectionnez le fuseau horaire',
select_date_formate: 'sélectionnez Date Formate',
select_financial_year: 'sélectionner lexercice'
},
update_app: {
title: "Mise à jour de l'application",
description: "mettre à jour la description de l'application",
check_update: 'Vérifier les mises à jour',
avail_update: 'Nouvelle mise à jour disponible',
next_version: 'Version suivante',
update: 'Mettre à jour maintenant',
update_progress: 'Mise à jour en cours...',
progress_text: "Cela ne prendra que quelques minutes. S'il vous plaît ne pas actualiser l'écran ou fermer la fenêtre avant la fin de la mise à jour",
update_success: "L'application a été mise à jour avec succès",
latest_message: 'Pas de mise a jour disponible! Vous êtes sur la dernière version.',
current_version: 'Version actuelle'
}
},
wizard: {
account_info: 'Information sur le compte',
account_info_desc: 'Les détails ci-dessous seront utilisés pour créer le compte administrateur principal. Aussi, vous pouvez modifier les détails à tout moment après la connexion.',
name: 'Nom',
email: 'Email',
password: 'Mot de passe',
confirm_password: 'Confirmez le mot de passe',
save_cont: 'Enregistrer continuer',
company_info: 'Informations sur la société',
company_info_desc: 'Ces informations seront affichées sur les factures. Notez que vous pouvez éditer ceci plus tard sur la page des paramètres.',
company_name: 'Nom de la compagnie',
company_logo: 'Logo dentreprise',
logo_preview: 'Aperçu du logo',
preferences: 'Préférences',
preferences_desc: 'Préférences par défaut pour le système.',
country: 'Pays',
state: 'Etat',
city: 'Ville',
address: 'Adresse',
street: 'Street1 ' | 'Rue # 2',
phone: 'Téléphone',
zip_code: 'Code postal',
go_back: 'Retourner',
currency: 'Devise',
language: 'La langue',
time_zone: 'Fuseau horaire',
fiscal_year: 'Année financière',
date_format: 'Format de date',
from_address: "De l'adresse",
username: "Nom d'utilisateur",
next: 'Suivant',
continue: 'Continuer',
database: {
database: 'URL du site et base de données',
connection: 'Connexion à la base de données',
host: 'Hôte de base de données',
port: 'Port de base de données',
password: 'Mot de passe de base de données',
app_url: 'Application URL',
username: "Nom d'utilisateur de la base de données",
db_name: 'Nom de la base de données',
desc: "Créez une base de données sur votre serveur et définissez les informations d'identification à l'aide du formulaire ci-dessous."
},
permissions: {
permissions: 'Les permissions',
permission_desc: "Vous trouverez ci-dessous la liste des autorisations de dossier requises pour le fonctionnement de l'application. Si la vérification des autorisations échoue, veillez à mettre à jour vos autorisations de dossier."
},
mail: {
host: 'Mail Host',
port: 'Port mail',
driver: 'Pilote de courrier',
password: 'Mot de passe 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',
username: "Mail Nom d'utilisateur",
mail_config: 'Configuration du courrier',
encryption: 'Chiffrement du courrier',
mail_config_desc: "Les détails ci-dessous seront utilisés pour mettre à jour l'environnement de messagerie. Aussi, vous pouvez modifier les détails à tout moment après la connexion."
},
req: {
system_req: 'Configuration requise',
php_req_version: 'Php (version {version} nécessaire)',
check_req: 'Vérifier les exigences',
system_req_desc: 'Crater a quelques exigences de serveur. Assurez-vous que votre serveur dispose de la version PHP requise et de toutes les extensions mentionnées ci-dessous.'
},
errors: {
migrate_failed: 'Migration impossible',
database_variables_save_error: 'Impossible de se connecter à la base de données avec les valeurs fournies.',
mail_variables_save_error: 'La configuration du courrier électronique a échoué.',
connection_failed: 'La connexion à la base de données a échoué'
},
success: {
mail_variables_save_successfully: 'Email configuré avec succès',
database_variables_save_successfully: 'Base de données configurée avec succès.'
}
},
layout_login: {
copyright_crater: 'Copyright @ Crater - 2019',
super_simple_invoicing: 'Super Simple Facturation',
for_freelancer: 'pour les pigistes et',
small_businesses: 'Petites entreprises ',
crater_help: 'Crater vous aide à suivre vos dépenses, à enregistrer vos paiements et à générer de belles',
invoices_and_estimates: 'factures et devis avec possibilité de choisir plusieurs modèles.'
},
validation: {
invalid_url: 'URL invalide (ex: http://www.crater.com)',
required: 'Champ requis',
email_incorrect: 'Adresse Email incorrecte.',
email_does_not_exist: "L'utilisateur avec un email donné n'existe pas",
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',
name_min_length: 'Le nom doit avoir au moins {count} lettres.',
enter_valid_tax_rate: 'Entrez un taux de taxe valide',
numbers_only: 'Chiffres uniquement.',
characters_only: 'Caractères seulement.',
password_incorrect: 'Les mots de passe doivent être identiques',
password_length: 'Le mot de passe doit comporter 5 caractères.',
qty_must_greater_than_zero: 'La quantité doit être supérieure à zéro.',
price_greater_than_zero: 'Le prix doit être supérieur à zéro.',
payment_greater_than_zero: 'Le paiement doit être supérieur à zéro.',
payment_greater_than_due_amount: 'Le paiement entré est plus que le montant dû de cette facture.',
quantity_maxlength: 'La quantité ne doit pas dépasser 20 chiffres.',
price_maxlength: 'Le prix ne doit pas dépasser 20 chiffres.',
price_minvalue: 'Le prix doit être supérieur à 0 chiffre',
amount_maxlength: 'Le montant ne doit pas dépasser 20 chiffres.',
amount_minvalue: 'Le montant doit être supérieur à 0 chiffre',
description_maxlength: 'La description ne doit pas dépasser 255 caractères.',
maximum_options_error: 'Maximum de {max} options sélectionnées. Commencez par supprimer une option sélectionnée pour en sélectionner une autre.',
notes_maxlength: 'Les notes ne doivent pas dépasser 255 caractères.',
address_maxlength: "L'adresse ne doit pas dépasser 255 caractères.",
ref_number_maxlength: 'Le numéro de référence ne doit pas dépasser 255 caractères.'
}
}

View File

@ -0,0 +1,814 @@
{
"navigation": {
"dashboard": "Tableau de bord",
"customers": "Cliente",
"items": "Articles",
"invoices": "Factures",
"expenses": "Les dépenses",
"estimates": "Estimations",
"payments": "Paiements",
"reports": "Rapports",
"settings": "Paramètres",
"logout": "Se déconnecter"
},
"general": {
"view_pdf": "Voir PDF",
"download_pdf": "Télécharger le PDF",
"save": "sauver",
"cancel": "Annuler",
"update": "Mise à jour",
"download": "Télécharger",
"from_date": "Partir de la date",
"to_date": "À ce jour",
"from": "De",
"to": "À",
"go_back": "Retourner",
"back_to_login": "Retour connexion?",
"home": "Accueil",
"filter": "Filtre",
"delete": "Effacer",
"edit": "Modifier",
"view": "Vue",
"add_new_item": "Ajoute un nouvel objet",
"clear_all": "Tout effacer",
"showing": "Montrant",
"of": "de",
"actions": "Actions",
"subtotal": "TOTAL",
"discount": "REMISE",
"fixed": "Fixée",
"percentage": "Pourcentage",
"tax": "IMPÔT",
"total_amount": "MONTANT TOTAL",
"bill_to": "facturer",
"ship_to": "Envoyez à",
"due": "Dû",
"draft": "Brouillon",
"sent": "Envoyée",
"all": "Tout",
"select_all": "Tout sélectionner",
"choose_file": "Cliquez ici pour choisir un fichier",
"choose_template": "Choisissez un modèle",
"choose": "Choisir",
"remove": "Retirer",
"powered_by": "Alimenté 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?",
"list_is_empty": "La liste est vide",
"no_tax_found": "Aucune taxe trouvée!",
"four_zero_four": "404",
"you_got_lost": "Oups! Vous vous êtes perdus!",
"go_home": "Rentrer chez soi",
"setting_updated": "Réglage mis à jour avec succès",
"select_state": "Sélectionnez l'état",
"select_country": "Choisissez le pays",
"select_city": "Sélectionnez une ville",
"street_1": "Rue 1",
"street_2": "Rue # 2",
"action_failed": "Action : échoué"
},
"dashboard": {
"select_year": "Sélectionnez lannée",
"cards": {
"due_amount": "Montant dû",
"customers": "Les clients",
"invoices": "Factures",
"estimates": "Estimations"
},
"chart_info": {
"total_sales": "Ventes",
"total_receipts": "Reçus",
"total_expense": "Les dépenses",
"net_income": "Revenu net",
"year": "Sélectionnez lannée"
},
"weekly_invoices": {
"title": "Factures hebdomadaires"
},
"monthly_chart": {
"title": "Ventes et dépenses"
},
"recent_invoices_card": {
"title": "Factures dues",
"due_on": "Due On",
"customer": "Cliente",
"amount_due": "Montant dû",
"actions": "Actions",
"view_all": "Voir tout"
},
"recent_estimate_card": {
"title": "Estimations récentes",
"date": "Date",
"customer": "Cliente",
"amount_due": "Montant dû",
"actions": "Actions",
"view_all": "Voir tout"
}
},
"tax_types": {
"name": "Nom",
"description": "La description",
"percent": "Pour cent",
"compound_tax": "Taxe composée"
},
"customers": {
"title": "Les 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",
"contact_name": "Nom du contact",
"amount_due": "Montant dû",
"email": "Email",
"address": "Adresse",
"phone": "Téléphone",
"website": "Site Internet",
"country": "Pays",
"state": "Etat",
"city": "Ville",
"zip_code": "Code postal",
"added_on": "Ajouté le",
"action": "action",
"password": "Mot de passe",
"street_number": "Numéro de rue",
"primary_currency": "Devise principale",
"add_new_customer": "Ajouter un nouveau client",
"save_customer": "Enregistrer le client",
"update_customer": "Mettre à jour le client",
"customer": "Client | Les clients",
"new_customer": "Nouveau client",
"edit_customer": "Modifier le client",
"basic_info": "Informations de base",
"billing_address": "Adresse de facturation",
"shipping_address": "Adresse de livraison",
"copy_billing_address": "Copier de la facturation",
"no_customers": "Pas encore de clients!",
"no_customers_found": "Aucun client trouvé!",
"list_of_customers": "Cette section contiendra la liste des clients.",
"primary_display_name": "Nom daffichage principal",
"select_state": "Sélectionnez létat",
"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",
"select_a_customer": "Sélectionnez un client",
"type_or_click": "Tapez ou cliquez pour sélectionner",
"confirm_delete": "Vous ne pourrez pas récupérer ce client | Vous ne pourrez pas récupérer ces clients",
"created_message": "Client créé avec succès",
"updated_message": "Client mis à jour avec succès",
"deleted_message": "Client supprimé avec succès | Les clients supprimés avec succès"
},
"items": {
"title": "Articles",
"items_list": "Liste darticles",
"name": "Nom",
"unit": "Unité",
"description": "La description",
"added_on": "Ajouté le",
"price": "Prix",
"date_of_creation": "Date de création",
"action": "action",
"add_item": "Ajouter un item",
"save_item": "Enregistrer lélément",
"update_item": "Mettre à jour lélément",
"item": "Article | Articles",
"add_new_item": "Ajoute un nouvel objet",
"new_item": "Nouvel article",
"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é",
"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",
"created_message": "Article créé avec succès",
"updated_message": "Élément mis à jour avec succès",
"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",
"days": "{jours} jours",
"months": "{mois} mois",
"years": "{années} Année",
"all": "Toute",
"paid": "Payé",
"unpaid": "Non payé",
"customer": "CLIENTE CLIENT",
"ref_no": "REF NO.",
"number": "NOMBRE",
"amount_due": "MONTANT DÛ",
"partially_paid": "Partiellement payé",
"total": "Totale",
"discount": "Remise",
"sub_total": "Total partiel",
"estimate_number": "Numéro destimation",
"ref_number": "Numéro de ref",
"contact": "Contact",
"add_item": "Ajouter un article",
"date": "Date",
"due_date": "Date déchéance",
"expiry_date": "Date dexpiration",
"status": "Statut",
"add_tax": "Ajouter une taxe",
"amount": "Montante",
"action": "action",
"notes": "Remarques",
"tax": "Impôt",
"estimate_template": "Modèle destimation",
"convert_to_invoice": "Convertir en facture",
"mark_as_sent": "Marquer comme envoyé",
"send_estimate": "Envoyer une estimation",
"record_payment": "Record de paiement",
"add_estimate": "Ajouter une estimation",
"save_estimate": "Sauvegarder lestimation",
"confirm_conversion": "Vous souhaitez convertir cette estimation 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",
"errors": {
"required": "Champ requis"
},
"accepted": "Accepté",
"sent": "Envoyée",
"draft": "Brouillon",
"declined": "Diminué",
"new_estimate": "Nouvelle estimation",
"add_new_estimate": "Ajouter une nouvelle estimation",
"update_Estimate": "Mise à jour de lestimation",
"edit_estimate": "Modifier lestimation",
"items": "articles",
"Estimate": "Estimation | Estimations",
"add_new_tax": "Ajouter une nouvelle taxe",
"no_estimates": "Aucune estimation pour le moment!",
"list_of_estimates": "Cette section contiendra la liste des estimations.",
"mark_as_rejected": "Marquer comme rejeté",
"mark_as_accepted": "Marquer comme accepté",
"marked_as_accepted_message": "Estimation marquée comme acceptée",
"marked_as_rejected_message": "Estimation marquée comme rejetée",
"confirm_delete": "Vous ne pourrez pas récupérer cette estimation | Vous ne pourrez pas récupérer ces estimations",
"created_message": "Estimation créée avec succès",
"updated_message": "Estimation mise à jour avec succès",
"deleted_message": "Estimation supprimée avec succès | Estimations supprimées avec succès",
"item": {
"title": "Titre de larticle",
"description": "La description",
"quantity": "Quantité",
"price": "Prix",
"discount": "Remise",
"total": "Totale",
"total_discount": "Remise totale",
"sub_total": "Total partiel",
"tax": "Impôt",
"amount": "Montante",
"select_an_item": "Tapez ou cliquez pour sélectionner un élément",
"type_item_description": "Type Item Description (optionnel)"
}
},
"invoices": {
"title": "Factures",
"invoices_list": "Liste de factures",
"days": "{jours} jours",
"months": "{mois} mois",
"years": "{années} Année",
"all": "Toute",
"paid": "Payé",
"unpaid": "Non payé",
"customer": "CLIENTE CLIENT",
"paid_status": "Statut payé",
"ref_no": "REF NO.",
"number": "NOMBRE",
"amount_due": "MONTANT DÛ",
"partially_paid": "Partiellement payé",
"total": "Totale Total",
"discount": "Remise",
"sub_total": "Total partiel",
"invoice": "Facture | Factures",
"invoice_number": "Numéro de facture",
"ref_number": "Numéro de ref",
"contact": "Contact",
"add_item": "Ajouter un article",
"date": "Date",
"due_date": "Date déchéance",
"status": "Statut",
"add_tax": "Ajouter une taxe",
"amount": "Montante Montant",
"action": "action",
"notes": "Remarques",
"view": "Vue",
"send_invoice": "Envoyer une facture",
"invoice_template": "Modèle de facture",
"template": "Modèle",
"mark_as_sent": "Marquer comme envoyé",
"invoice_mark_as_sent": "Cette facture sera marquée comme envoyé",
"confirm_send": "Cette facture sera envoyée par courrier électronique au client.",
"invoice_date": "Date de facturation",
"record_payment": "Record de paiement",
"add_new_invoice": "Ajouter une nouvelle facture",
"update_expense": "Frais de mise à jour",
"edit_invoice": "Modifier la facture",
"new_invoice": "Nouvelle facture",
"save_invoice": "Enregistrer la facture",
"update_invoice": "Mettre à jour la facture",
"add_new_tax": "Ajouter une nouvelle taxe",
"no_invoices": "Aucune facture pour le moment!",
"list_of_invoices": "Cette section contiendra la liste des factures.",
"select_invoice": "Sélectionnez facture",
"mark_as_sent_successfully": "Facture marquée comme envoyée avec succès",
"send_invoice_successfully": "Facture envoyée avec succès",
"item": {
"title": "Titre de larticle",
"description": "La description",
"quantity": "Quantité",
"price": "Prix",
"discount": "Remise",
"total": "Totale Total",
"total_discount": "Remise totale",
"sub_total": "Total partiel",
"tax": "Impôt",
"amount": "Montante Montant",
"select_an_item": "Tapez ou cliquez pour sélectionner un élément",
"type_item_description": "Type Item Description (optionnel)"
},
"payment_attached_message": "Un paiement est déjà associé à l'une des factures sélectionnées. Assurez-vous deffacer dabord les paiements en pièce jointe afin de procéder à la suppression.",
"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",
"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"
},
"credit_notes": {
"title": "Notes de crédit",
"credit_notes_list": "Liste des notes de crédit",
"credit_notes": "Notes de crédit",
"contact": "Contact",
"date": "Date",
"amount": "Montante Montant",
"action": "action",
"credit_number": "Numéro de crédit",
"notes": "Remarques",
"confirm_delete": "Voulez-vous supprimer cet avoir?",
"item": {
"title": "Titre de larticle",
"description": "La description",
"quantity": "Quantité",
"price": "Prix",
"discount": "Remise",
"total": "Totale Total",
"total_discount": "Remise totale",
"sub_total": "Total partiel",
"tax": "Impôt"
}
},
"payments": {
"title": "Paiements",
"payments_list": "Liste de paiements",
"record_payment": "Record de paiement",
"customer": "Cliente Client",
"date": "Date",
"amount": "Montante Montant",
"action": "action",
"payment_number": "Numéro de paiement",
"payment_mode": "Mode de paiement",
"invoice": "Facture dachat",
"note": "Remarque",
"add_payment": "Ajouter un paiement",
"new_payment": "Nouveau paiement",
"edit_payment": "Modifier le paiement",
"view_payment": "Voir le paiement",
"add_new_payment": "Ajouter un nouveau paiement",
"save_payment": "Enregistrer le paiement",
"update_payment": "Mettre à jour le paiement",
"payment": "Paiement | Paiements",
"no_payments": "Aucun paiement pour le moment!",
"list_of_payments": "Cette section contiendra la liste des paiements",
"select_payment_mode": "Sélectionnez le mode de paiement",
"confirm_delete": "Vous ne pourrez pas récupérer ce paiement | Vous ne pourrez pas récupérer ces paiements",
"created_message": "Paiement créé avec succès",
"updated_message": "Paiement mis à jour avec succès",
"deleted_message": "Paiement supprimé avec succès | Paiements supprimés avec succès",
"invalid_amount_message": "Le montant du paiement est invalide"
},
"expenses": {
"title": "Les dépenses",
"expenses_list": "Liste des dépenses",
"expense_title": "Titre",
"contact": "Contact",
"category": "Catégorie",
"from_date": "Partir de la date",
"to_date": "À ce jour",
"expense_date": "Date",
"description": "La description",
"receipt": "Le reçu",
"amount": "Montante Montant",
"action": "action",
"note": "Remarque",
"category_id": "Identifiant de catégorie",
"date": "Date de dépense",
"add_expense": "Ajouter une dépense",
"add_new_expense": "Ajouter une nouvelle dépense",
"save_expense": "Économiser des dépenses",
"update_expense": "Frais de mise à jour",
"download_receipt": "Télécharger le reçu",
"edit_expense": "Modifier les dépenses",
"new_expense": "Nouvelle dépense",
"expense": "Frais | Les dépenses",
"no_expenses": "Pas de dépenses pour le moment!",
"list_of_expenses": "Cette section contiendra la liste des dépenses.",
"confirm_delete": "Vous ne pourrez pas récupérer cette dépense | Vous ne pourrez pas récupérer ces frais",
"created_message": "Dépense créée avec succès",
"updated_message": "Dépense mise à jour avec succès",
"deleted_message": "Dépense supprimée avec succès | Dépenses supprimées avec succès",
"categories": {
"categories_list": "Liste des catégories",
"title": "Titre",
"name": "Nom",
"description": "La description",
"amount": "Montante Montant",
"actions": "Actions",
"add_category": "ajouter une catégorie",
"new_category": "Nouvelle catégorie",
"category": "Catégorie | Les catégories",
"select_a_category": "choisissez une catégorie"
}
},
"login": {
"email": "Email",
"password": "Mot de passe",
"forgot_password": "Mot de passe oublié?",
"or_signIn_with": "ou Connectez-vous avec:",
"login": "Sidentifier",
"register": "Sinscrire",
"reset_password": "réinitialiser le mot de passe",
"enter_email": "Entrer email",
"enter_password": "Entrer le mot de passe",
"retype_password": "Retaper le mot de passe",
"login_placeholder": "mail@example.com"
},
"reports": {
"title": "rapport",
"from_date": "Partir de la date",
"to_date": "À ce jour",
"status": "Statut",
"paid": "Payé",
"unpaid": "Non payé",
"download_pdf": "Télécharger le PDF",
"view_pdf": "Voir PDF",
"update_report": "Rapport de mise à jour",
"report": "Rapport | Rapports",
"profit_loss": {
"profit_loss": "Perte de profit",
"to_date": "À ce jour",
"from_date": "Partir de la date",
"date_range": "Sélectionner une plage de dates"
},
"sales": {
"sales": "Ventes",
"date_range": "Sélectionner une plage de dates",
"to_date": "À ce jour",
"from_date": "Partir de la date",
"report_type": "Type de rapport"
},
"taxes": {
"taxes": "Les taxes",
"to_date": "À ce jour",
"from_date": "Partir de la date",
"date_range": "Sélectionner une plage de dates"
},
"errors": {
"required": "Champ requis"
},
"invoices": {
"invoice": "Facture dachat",
"invoice_date": "Date de facturation",
"due_date": "Date déchéance",
"amount": "Montante ",
"contact_name": "Nom du contact",
"status": "Statut"
},
"estimates": {
"estimate": "Estimation",
"estimate_date": "Date destimation",
"due_date": "Date déchéance",
"estimate_number": "Numéro destimation",
"ref_number": "Numéro de ref",
"amount": "Montante",
"contact_name": "Nom du contact",
"status": "Statut"
},
"expenses": {
"expenses": "Les dépenses",
"category": "Catégorie",
"date": "Date",
"amount": "Montante",
"to_date": "À ce jour",
"from_date": "Partir de la date",
"date_range": "Sélectionner une plage de dates"
}
},
"settings": {
"menu_title": {
"account_settings": "Paramètres du compte",
"company_information": "Informations sur la société",
"preferences": "Préférences",
"notifications": "Les notifications",
"tax_types": "Types de taxe",
"expense_category": "Catégories de dépenses",
"update_app": "Mise à jour de l'application"
},
"title": "Paramètres",
"setting": "Paramètres | Paramètres",
"general": "Générale",
"language": "La langue",
"primary_currency": "Devise principale",
"timezone": "Fuseau horaire",
"date_format": "Format de date",
"currencies": {
"title": "Monnaies",
"currency": "Monnaie | Monnaies",
"currencies_list": "Liste des devises",
"select_currency": "Sélectionnez la devise",
"name": "Nom",
"code": "Code",
"symbol": "symbole",
"precision": "Précision",
"thousand_separator": "Mille séparateur",
"decimal_separator": "Séparateur décimal",
"position": "Position",
"position_of_symbol": "Position du symbole",
"right": "Droite",
"left": "La gauche",
"action": "action",
"add_currency": "Ajouter une devise"
},
"mail": {
"host": "Mail Host",
"port": "Port mail",
"driver": "Pilote de courrier",
"password": "Mot de passe 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",
"username": "Mail Nom d'utilisateur",
"mail_config": "Configuration du courrier",
"encryption": "Chiffrement du courrier",
"mail_config_desc": "Les détails ci-dessous seront utilisés pour mettre à jour l'environnement de messagerie. Aussi, vous pouvez modifier les détails à tout moment après la connexion."
},
"pdf": {
"title": "Paramètre PDF",
"footer_text": "Pied de page texte",
"pdf_layout": "Mise en page PDF"
},
"company_info": {
"company_info": "Information dentreprise",
"company_name": "Nom de la compagnie",
"company_logo": "Logo dentreprise",
"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",
"state": "Etat",
"city": "Ville",
"address": "Adresse",
"zip": "Zip",
"save": "sauver",
"updated_message": "Informations sur la société mises à jour avec succès"
},
"account_settings": {
"profile_picture": "Image de profil",
"name": "Nom",
"email": "Email",
"password": "Mot de passe",
"confirm_password": "Confirmez le mot de passe",
"account_settings": "Paramètres du compte",
"save": "sauver",
"section_description": "Vous pouvez mettre à jour votre nom, votre email et votre mot de passe en utilisant le formulaire ci-dessous.",
"updated_message": "Paramètres du compte mis à jour avec succès"
},
"user_profile": {
"name": "Nom",
"email": "Email",
"password": "Mot de passe",
"confirm_password": "Confirmez le mot de passe"
},
"notification": {
"title": "Notification",
"email": "Envoyer des notifications à",
"description": "Quelles notifications par courrier électronique souhaitez-vous recevoir lorsque quelque chose change?",
"invoice_viewed": "Facture consultée",
"invoice_viewed_desc": "Lorsque votre client visualise la facture envoyée via le tableau de bord du cratère.",
"estimate_viewed": "Estimation vue",
"estimate_viewed_desc": "Lorsque votre client visualise le devis envoyé via le tableau de bord du cratère.",
"save": "sauver",
"email_save_message": "Email enregistré avec succès",
"invoice_viewed_message": "Facture consultée",
"estimate_viewed_message": "Estimation vue",
"please_enter_email": "S il vous plaît entrer email"
},
"tax_types": {
"title": "Types de taxe",
"add_tax": "Ajouter une taxe",
"description": "Vous pouvez ajouter ou supprimer des taxes à votre guise. Crater prend en charge les taxes sur les articles individuels ainsi que sur la facture.",
"add_new_tax": "Ajouter une nouvelle taxe",
"tax_settings": "Paramètres de taxe",
"tax_per_item": "Taxe par article",
"tax_name": "Nom de la taxe",
"compound_tax": "Taxe composée",
"percent": "Pour cent",
"action": "action",
"tax_setting_description": "Activez cette option si vous souhaitez ajouter des taxes à des postes de facture individuels. Par défaut, les taxes sont ajoutées directement à la facture.",
"created_message": "Type de taxe créé avec succès",
"updated_message": "Type de taxe mis à jour avec succès",
"deleted_message": "Type de taxe supprimé avec succès",
"confirm_delete": "Vous ne pourrez pas récupérer ce type de taxe",
"already_in_use": "La taxe est déjà utilisée"
},
"expense_category": {
"title": "Catégories de dépenses",
"action": "action",
"description": "Des catégories sont requises pour ajouter des entrées de dépenses. Vous pouvez ajouter ou supprimer ces catégories selon vos préférences.",
"add_new_category": "Ajouter une nouvelle catégorie",
"category_name": "Nom de catégorie",
"category_description": "La description",
"created_message": "Catégorie de dépenses créée avec succès",
"deleted_message": "La catégorie de dépenses a été supprimée avec succès",
"updated_message": "Catégorie de dépenses mise à jour avec succès",
"confirm_delete": "Vous ne pourrez pas récupérer cette catégorie de dépenses",
"already_in_use": "La catégorie est déjà utilisée"
},
"preferences": {
"currency": "Devise",
"language": "La langue",
"time_zone": "Fuseau horaire",
"fiscal_year": "Année financière",
"date_format": "Format de date",
"discount_setting": "Réglage de remise",
"discount_per_item": "Remise par article",
"discount_setting_description": "Activez cette option si vous souhaitez ajouter une remise à des postes de facture individuels. Par défaut, les remises sont ajoutées directement à la facture.",
"save": "sauver",
"preference": "Préférence | Préférences",
"general_settings": "Préférences par défaut pour le système.",
"updated_message": "Préférences mises à jour avec succès",
"set_discount_per_item_message": "Jeu de remise par article",
"select_language": "Choisir la langue",
"select_time_zone": "sélectionnez le fuseau horaire",
"select_date_formate": "sélectionnez Date Formate",
"select_financial_year": "sélectionner lexercice"
},
"update_app": {
"title": "Mise à jour de l'application",
"description": "mettre à jour la description de l'application",
"check_update": "Vérifier les mises à jour",
"avail_update": "Nouvelle mise à jour disponible",
"next_version": "Version suivante",
"update": "Mettre à jour maintenant",
"update_progress": "Mise à jour en cours...",
"progress_text": "Cela ne prendra que quelques minutes. S'il vous plaît ne pas actualiser l'écran ou fermer la fenêtre avant la fin de la mise à jour",
"update_success": "App a été mis à jour! Veuillez patienter pendant le rechargement automatique de la fenêtre de votre navigateur.",
"latest_message": "Pas de mise a jour disponible! Vous êtes sur la dernière version.",
"current_version": "Version actuelle"
}
},
"wizard": {
"account_info": "Information sur le compte",
"account_info_desc": "Les détails ci-dessous seront utilisés pour créer le compte administrateur principal. Aussi, vous pouvez modifier les détails à tout moment après la connexion.",
"name": "Nom",
"email": "Email",
"password": "Mot de passe",
"confirm_password": "Confirmez le mot de passe",
"save_cont": "Enregistrer continuer",
"company_info": "Informations sur la société",
"company_info_desc": "Ces informations seront affichées sur les factures. Notez que vous pouvez éditer ceci plus tard sur la page des paramètres.",
"company_name": "Nom de la compagnie",
"company_logo": "Logo dentreprise",
"logo_preview": "Aperçu du logo",
"preferences": "Préférences",
"preferences_desc": "Préférences par défaut pour le système.",
"country": "Pays",
"state": "Etat",
"city": "Ville",
"address": "Adresse",
"street": "Rue 1 | Rue 2",
"phone": "Téléphone",
"zip_code": "Code postal",
"go_back": "Retourner",
"currency": "Devise",
"language": "La langue",
"time_zone": "Fuseau horaire",
"fiscal_year": "Année financière",
"date_format": "Format de date",
"from_address": "De l'adresse",
"username": "Nom d'utilisateur",
"next": "Suivant",
"continue": "Continuer",
"database": {
"database": "URL du site et base de données",
"connection": "Connexion à la base de données",
"host": "Hôte de base de données",
"port": "Port de base de données",
"password": "Mot de passe de base de données",
"app_url": "Application URL",
"username": "Nom d'utilisateur de la base de données",
"db_name": "Nom de la base de données",
"desc": "Créez une base de données sur votre serveur et définissez les informations d'identification à l'aide du formulaire ci-dessous."
},
"permissions": {
"permissions": "Les permissions",
"permission_confirm_title": "Es-tu sur de vouloir continuer?",
"permission_confirm_desc": "La vérification de l\"autorisation du dossier a échoué",
"permission_desc": "Vous trouverez ci-dessous la liste des autorisations de dossier requises pour le fonctionnement de l'application. Si la vérification des autorisations échoue, veillez à mettre à jour vos autorisations de dossier."
},
"mail": {
"host": "Mail Host",
"port": "Port mail",
"driver": "Pilote de courrier",
"password": "Mot de passe 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",
"username": "Mail Nom d'utilisateur",
"mail_config": "Configuration du courrier",
"encryption": "Chiffrement du courrier",
"mail_config_desc": "Les détails ci-dessous seront utilisés pour mettre à jour l'environnement de messagerie. Aussi, vous pouvez modifier les détails à tout moment après la connexion."
},
"req": {
"system_req": "Configuration requise",
"php_req_version": "Php (version {version} nécessaire)",
"check_req": "Vérifier les exigences",
"system_req_desc": "Crater a quelques exigences de serveur. Assurez-vous que votre serveur dispose de la version PHP requise et de toutes les extensions mentionnées ci-dessous."
},
"errors": {
"migrate_failed": "Migration impossible",
"database_variables_save_error": "Impossible de se connecter à la base de données avec les valeurs fournies.",
"mail_variables_save_error": "La configuration du courrier électronique a échoué.",
"connection_failed": "La connexion à la base de données a échoué"
},
"success": {
"mail_variables_save_successfully": "Email configuré avec succès",
"database_variables_save_successfully": "Base de données configurée avec succès."
}
},
"layout_login": {
"copyright_crater": "Copyright @ Crater - 2019",
"super_simple_invoicing": "Super Simple Facturation",
"for_freelancer": "pour les pigistes et",
"small_businesses": "Petites entreprises ",
"crater_help": "Crater vous aide à suivre vos dépenses, à enregistrer vos paiements et à générer de belles",
"invoices_and_estimates": "factures et devis avec possibilité de choisir plusieurs modèles."
},
"validation": {
"invalid_url": "URL invalide (ex: http://www.crater.com)",
"required": "Champ requis",
"email_incorrect": "Adresse Email incorrecte.",
"email_does_not_exist": "L'utilisateur avec un email donné n'existe pas",
"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",
"name_min_length": "Le nom doit avoir au moins {count} lettres.",
"enter_valid_tax_rate": "Entrez un taux de taxe valide",
"numbers_only": "Chiffres uniquement.",
"characters_only": "Caractères seulement.",
"password_incorrect": "Les mots de passe doivent être identiques",
"password_length": "Le mot de passe doit comporter 5 caractères.",
"qty_must_greater_than_zero": "La quantité doit être supérieure à zéro.",
"price_greater_than_zero": "Le prix doit être supérieur à zéro.",
"payment_greater_than_zero": "Le paiement doit être supérieur à zéro.",
"payment_greater_than_due_amount": "Le paiement entré est plus que le montant dû de cette facture.",
"quantity_maxlength": "La quantité ne doit pas dépasser 20 chiffres.",
"price_maxlength": "Le prix ne doit pas dépasser 20 chiffres.",
"price_minvalue": "Le prix doit être supérieur à 0 chiffre",
"amount_maxlength": "Le montant ne doit pas dépasser 20 chiffres.",
"amount_minvalue": "Le montant doit être supérieur à 0 chiffre",
"description_maxlength": "La description ne doit pas dépasser 255 caractères.",
"maximum_options_error": "Maximum de {max} options sélectionnées. Commencez par supprimer une option sélectionnée pour en sélectionner une autre.",
"notes_maxlength": "Les notes ne doivent pas dépasser 255 caractères.",
"address_maxlength": "L'adresse ne doit pas dépasser 255 caractères.",
"ref_number_maxlength": "Le numéro de référence ne doit pas dépasser 255 caractères."
}
}

View File

@ -1,8 +1,8 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import en from './en'
import fr from './fr'
import es from './es'
import en from './en.json'
import fr from './fr.json'
import es from './es.json'
Vue.use(VueI18n)

View File

@ -66,6 +66,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'
@ -309,6 +310,11 @@ const routes = [
name: 'company.info',
component: CompanyInfo
},
{
path: 'customization',
name: 'customization',
component: Customization
},
{
path: 'user-profile',
name: 'user.profile',

View File

@ -9,10 +9,11 @@ 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)

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

@ -36,7 +36,9 @@ export const addCustomer = ({ commit, dispatch, state }, data) => {
export const updateCustomer = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.put(`/api/customers/${data.id}`, data).then((response) => {
commit(types.UPDATE_CUSTOMER, response.data)
if(response.data.success){
commit(types.UPDATE_CUSTOMER, response.data)
}
resolve(response)
}).catch((err) => {
reject(err)

View File

@ -12,11 +12,7 @@ export const loadData = ({ commit, dispatch, state }, id) => {
export const editCompany = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.post('/api/settings/company', data, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then((response) => {
window.axios.post('/api/settings/company', data).then((response) => {
// commit(types.UPDATE_ITEM, response.data)
resolve(response)
}).catch((err) => {

View File

@ -1,8 +1,9 @@
// import * as types from './mutation-types'
import * as types from './mutation-types'
export const loadData = ({ commit, dispatch, state }, id) => {
return new Promise((resolve, reject) => {
window.axios.get(`/api/settings/profile`).then((response) => {
commit(types.SET_USER, response.data)
resolve(response)
}).catch((err) => {
reject(err)
@ -13,7 +14,29 @@ export const loadData = ({ commit, dispatch, state }, id) => {
export const editUser = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.put('/api/settings/profile', data).then((response) => {
// commit(types.UPDATE_USER, response.data)
commit(types.UPDATE_USER, response.data)
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
export const uploadOnboardAvatar = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.post(`/api/admin/profile/upload-avatar`, data).then((response) => {
commit(types.UPDATE_USER, response.data.user)
resolve(response)
}).catch((err) => {
reject(err)
})
})
}
export const uploadAvatar = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => {
window.axios.post('/api/settings/profile/upload-avatar', data).then((response) => {
commit(types.UPDATE_USER, response.data.user)
resolve(response)
}).catch((err) => {
reject(err)

View File

@ -1,2 +1,3 @@
export const SET_USER = 'SET_USER'
export const UPDATE_USER = 'UPDATE_USER'
export const UPDATE_USER_AVATAR = 'UPDATE_USER_AVATAR'

View File

@ -2,10 +2,14 @@ import * as types from './mutation-types'
export default {
[types.SET_USER] (state, data) {
state.user = data.user
state.user = data
},
[types.UPDATE_USER] (state, data) {
state.user = data
},
[types.UPDATE_USER_AVATAR] (state, data) {
state.user.avatar = data.avatar
}
}

View File

@ -3,8 +3,8 @@ export default {
phone: null,
address_street_1: null,
address_street_2: null,
city_id: null,
state_id: null,
city: null,
state: null,
country_id: null,
zip: null,
type: null

View File

@ -61,6 +61,7 @@
<base-select
v-model="currency"
:options="currencies"
:custom-label="currencyNameWithCode"
:allow-empty="false"
:searchable="true"
:show-labels="false"
@ -119,16 +120,10 @@
</div>
<div class="form-group">
<label class="form-label">{{ $t('customers.state') }}</label>
<base-select
v-model="billing_state"
:options="billingStates"
:searchable="true"
:show-labels="false"
:tabindex="9"
:disabled="isDisabledBillingState"
:placeholder="$t('general.select_state')"
label="name"
track-by="id"
<base-input
v-model="billing.state"
name="billing.state"
type="text"
/>
</div>
<div class="form-group">
@ -167,7 +162,7 @@
:options="billingCountries"
:searchable="true"
:show-labels="false"
:allow-empty="false"
:allow-empty="true"
:tabindex="8"
:placeholder="$t('general.select_country')"
label="name"
@ -176,16 +171,10 @@
</div>
<div class="form-group">
<label class="form-label">{{ $t('customers.city') }}</label>
<base-select
v-model="billing_city"
:options="billingCities"
:searchable="true"
:show-labels="false"
:disabled="isDisabledBillingCity"
:tabindex="10"
:placeholder="$t('general.select_city')"
label="name"
track-by="id"
<base-input
v-model="billing.city"
name="billing.city"
type="text"
/>
</div>
<div class="form-group">
@ -233,16 +222,10 @@
</div>
<div class="form-group">
<label class="form-label">{{ $t('customers.state') }}</label>
<base-select
v-model="shipping_state"
:options="shippingStates"
:searchable="true"
:show-labels="false"
:tabindex="17"
:disabled="isDisabledShippingState"
:placeholder="$t('general.select_state')"
label="name"
track-by="id"
<base-input
v-model="shipping.state"
name="shipping.state"
type="text"
/>
</div>
<div class="form-group">
@ -282,7 +265,7 @@
:searchable="true"
:show-labels="false"
:tabindex="16"
:allow-empty="false"
:allow-empty="true"
:placeholder="$t('general.select_country')"
label="name"
track-by="id"
@ -290,16 +273,10 @@
</div>
<div class="form-group">
<label class="form-label">{{ $t('customers.city') }}</label>
<base-select
v-model="shipping_city"
:options="shippingCities"
:searchable="true"
:show-labels="false"
:tabindex="18"
:disabled="isDisabledShippingCity"
:placeholder="$t('general.select_city')"
label="name"
track-by="id"
<base-input
v-model="shipping.city"
name="shipping.city"
type="text"
/>
</div>
<div class="form-group">
@ -344,7 +321,7 @@ import { mapActions, mapGetters } from 'vuex'
import MultiSelect from 'vue-multiselect'
import { validationMixin } from 'vuelidate'
import AddressStub from '../../stub/address'
const { required, minLength, email, numeric, url, maxLength } = require('vuelidate/lib/validators')
const { required, minLength, email, url, maxLength } = require('vuelidate/lib/validators')
export default {
components: { MultiSelect },
@ -366,8 +343,8 @@ export default {
billing: {
name: null,
country_id: null,
state_id: null,
city_id: null,
state: null,
city: null,
phone: null,
zip: null,
address_street_1: null,
@ -377,8 +354,8 @@ export default {
shipping: {
name: null,
country_id: null,
state_id: null,
city_id: null,
state: null,
city: null,
phone: null,
zip: null,
address_street_1: null,
@ -386,26 +363,12 @@ export default {
type: 'shipping'
},
currencyList: [],
isDisabledBillingState: true,
isDisabledBillingCity: true,
isDisabledShippingState: true,
isDisabledShippingCity: true,
billing_country: null,
billing_city: null,
billing_state: null,
shipping_country: null,
shipping_city: null,
shipping_state: null,
billingCountries: [],
billingStates: [],
billingCities: [],
shippingCountries: [],
shippingStates: [],
shippingCities: []
shippingCountries: []
}
},
validations: {
@ -448,6 +411,36 @@ export default {
return true
}
return false
},
hasBillingAdd () {
let billing = this.billing
if (
billing.name ||
billing.country_id ||
billing.state ||
billing.city ||
billing.phone ||
billing.zip ||
billing.address_street_1 ||
billing.address_street_2) {
return true
}
return false
},
hasShippingAdd () {
let shipping = this.shipping
if (
shipping.name ||
shipping.country_id ||
shipping.state ||
shipping.city ||
shipping.phone ||
shipping.zip ||
shipping.address_street_1 ||
shipping.address_street_2) {
return true
}
return false
}
},
watch: {
@ -455,60 +448,16 @@ export default {
if (newCountry) {
this.billing.country_id = newCountry.id
this.isDisabledBillingState = false
this.billing_state = null
this.billing_city = null
this.fetchBillingState()
}
},
billing_state (newState) {
if (newState) {
this.billing.state_id = newState.id
this.isDisabledBillingCity = false
this.billing_city = null
this.fetchBillingCities()
return true
}
this.billing_city = null
this.isDisabledBillingCity = true
return true
},
billing_city (newCity) {
if (newCity) {
this.billing.city_id = newCity.id
} else {
this.billing.country_id = null
}
},
shipping_country (newCountry) {
if (newCountry) {
this.shipping.country_id = newCountry.id
this.isDisabledShippingState = false
this.fetchShippingState()
if (this.isCopyFromBilling) {
return true
}
this.shipping_state = null
this.shipping_city = null
return true
}
},
shipping_state (newState) {
if (newState) {
this.shipping.state_id = newState.id
this.isDisabledShippingCity = false
this.fetchShippingCities()
if (this.isCopyFromBilling) {
this.isCopyFromBilling = false
return true
}
this.shipping_city = null
return true
}
this.shipping_city = null
this.isDisabledShippingCity = true
return true
},
shipping_city (newCity) {
if (newCity) {
this.shipping.city_id = newCity.id
} else {
this.shipping.country_id = null
}
}
},
@ -521,6 +470,9 @@ export default {
}
},
methods: {
currencyNameWithCode ({name, code}) {
return `${code} - ${name}`
},
...mapActions('customer', [
'addCustomer',
'fetchCustomer',
@ -528,7 +480,14 @@ export default {
]),
async loadCustomer () {
let { data: { customer, currencies, currency } } = await this.fetchCustomer(this.$route.params.id)
this.formData = customer
this.formData.id = customer.id
this.formData.name = customer.name
this.formData.contact_name = customer.contact_name
this.formData.email = customer.email
this.formData.phone = customer.phone
this.formData.currency_id = customer.currency_id
this.formData.website = customer.website
if (customer.billing_address) {
this.billing = customer.billing_address
@ -577,7 +536,16 @@ export default {
if (this.$v.$invalid) {
return true
}
this.formData.addresses = [{...this.billing}, {...this.shipping}]
if (this.hasBillingAdd && this.hasShippingAdd) {
this.formData.addresses = [{...this.billing}, {...this.shipping}]
} else {
if (this.hasBillingAdd) {
this.formData.addresses = [{...this.billing}]
}
if (this.hasShippingAdd) {
this.formData.addresses = [{...this.shipping}]
}
}
if (this.isEdit) {
if (this.currency) {
@ -586,11 +554,16 @@ export default {
this.isLoading = true
try {
let response = await this.updateCustomer(this.formData)
if (response.data) {
if (response.data.success) {
window.toastr['success'](this.$t('customers.updated_message'))
this.$router.push('/admin/customers')
this.isLoading = false
return true
} else {
this.isLoading = false
if (response.data.error) {
window.toastr['error'](this.$t('validation.email_already_taken'))
}
}
} catch (err) {
if (err.response.data.errors.email) {
@ -619,42 +592,6 @@ export default {
}
}
}
},
async fetchBillingState () {
let res = await window.axios.get(`/api/states/${this.billing_country.id}`)
if (res) {
this.billingStates = res.data.states
}
if (this.isEdit) {
this.billing_state = this.billingStates.find((state) => state.id === this.billing.state_id)
}
},
async fetchBillingCities () {
let res = await window.axios.get(`/api/cities/${this.billing_state.id}`)
if (res) {
this.billingCities = res.data.cities
}
if (this.isEdit) {
this.billing_city = this.billingCities.find((city) => city.id === this.billing.city_id)
}
},
async fetchShippingState () {
let res = await window.axios.get(`/api/states/${this.shipping_country.id}`)
if (res) {
this.shippingStates = res.data.states
}
if (this.isEdit) {
this.shipping_state = this.shippingStates.find((s) => s.id === this.shipping.state_id)
}
},
async fetchShippingCities () {
let res = await window.axios.get(`/api/cities/${this.shipping_state.id}`)
if (res) {
this.shippingCities = res.data.cities
}
if (this.isEdit) {
this.shipping_city = this.shippingCities.find((c) => c.id === this.shipping.city_id)
}
}
}
}

View File

@ -32,8 +32,8 @@
class="show-customer"
>
<div class="row px-2 mt-1">
<div class="col col-6">
<div v-if="selectedCustomer.billing_address != null" class="row address-menu">
<div v-if="selectedCustomer.billing_address" class="col col-6">
<div class="row address-menu">
<label class="col-sm-4 px-2 title">{{ $t('general.bill_to') }}</label>
<div class="col-sm p-0 px-2 content">
<label v-if="selectedCustomer.billing_address.name">
@ -46,7 +46,7 @@
{{ selectedCustomer.billing_address.address_street_2 }}
</label>
<label v-if="selectedCustomer.billing_address.city && selectedCustomer.billing_address.state">
{{ selectedCustomer.billing_address.city.name }}, {{ selectedCustomer.billing_address.state.name }} {{ selectedCustomer.billing_address.zip }}
{{ selectedCustomer.billing_address.city }}, {{ selectedCustomer.billing_address.state }} {{ selectedCustomer.billing_address.zip }}
</label>
<label v-if="selectedCustomer.billing_address.country">
{{ selectedCustomer.billing_address.country.name }}
@ -57,8 +57,8 @@
</div>
</div>
</div>
<div class="col col-6">
<div v-if="selectedCustomer.shipping_address != null" class="row address-menu">
<div v-if="selectedCustomer.shipping_address" class="col col-6">
<div class="row address-menu">
<label class="col-sm-4 px-2 title">{{ $t('general.ship_to') }}</label>
<div class="col-sm p-0 px-2 content">
<label v-if="selectedCustomer.shipping_address.name">
@ -71,7 +71,7 @@
{{ selectedCustomer.shipping_address.address_street_2 }}
</label>
<label v-if="selectedCustomer.shipping_address.city && selectedCustomer.shipping_address">
{{ selectedCustomer.shipping_address.city.name }}, {{ selectedCustomer.shipping_address.state.name }} {{ selectedCustomer.shipping_address.zip }}
{{ selectedCustomer.shipping_address.city }}, {{ selectedCustomer.shipping_address.state }} {{ selectedCustomer.shipping_address.zip }}
</label>
<label v-if="selectedCustomer.shipping_address.country" class="country">
{{ selectedCustomer.shipping_address.country.name }}
@ -84,7 +84,7 @@
</div>
</div>
<div class="customer-content mb-1">
<label class="email">{{ selectedCustomer.email ? selectedCustomer.email : selectedCustomer.name }}</label>
<label class="email">{{ selectedCustomer.name }}</label>
<label class="action" @click="removeCustomer">{{ $t('general.remove') }}</label>
</div>
</div>
@ -127,14 +127,15 @@
<div class="row mt-4">
<div class="col collapse-input">
<label>{{ $t('estimates.estimate_number') }}<span class="text-danger"> * </span></label>
<base-input
:invalid="$v.newEstimate.estimate_number.$error"
:read-only="true"
v-model="newEstimate.estimate_number"
<base-prefix-input
v-model="estimateNumAttribute"
:invalid="$v.estimateNumAttribute.$error"
:prefix="estimatePrefix"
icon="hashtag"
@input="$v.newEstimate.estimate_number.$touch()"
@input="$v.estimateNumAttribute.$touch()"
/>
<span v-show="$v.newEstimate.estimate_number.$error && !$v.newEstimate.estimate_number.required" class="text-danger mt-1"> {{ $tc('estimates.errors.required') }} </span>
<span v-show="$v.estimateNumAttribute.$error && !$v.estimateNumAttribute.required" class="text-danger mt-1"> {{ $tc('estimates.errors.required') }} </span>
<span v-show="!$v.estimateNumAttribute.numeric" class="text-danger mt-1"> {{ $tc('validation.numbers_only') }} </span>
</div>
<div class="col collapse-input">
<label>{{ $t('estimates.ref_number') }}</label>
@ -320,7 +321,7 @@ import { validationMixin } from 'vuelidate'
import Guid from 'guid'
import TaxStub from '../../stub/tax'
import Tax from './EstimateTax'
const { required, between, maxLength } = require('vuelidate/lib/validators')
const { required, between, maxLength, numeric } = require('vuelidate/lib/validators')
export default {
components: {
@ -361,7 +362,9 @@ export default {
discountPerItem: null,
initLoading: false,
isLoading: false,
maxDiscount: 0
maxDiscount: 0,
estimatePrefix: null,
estimateNumAttribute: null
}
},
validations () {
@ -373,9 +376,6 @@ export default {
expiry_date: {
required
},
estimate_number: {
required
},
discount_val: {
between: between(0, this.subtotal)
},
@ -388,6 +388,10 @@ export default {
},
selectedCustomer: {
required
},
estimateNumAttribute: {
required,
numeric
}
}
},
@ -559,6 +563,8 @@ export default {
this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency
this.estimateTemplates = response.data.estimateTemplates
this.estimatePrefix = response.data.estimate_prefix
this.estimateNumAttribute = response.data.nextEstimateNumber
}
this.initLoading = false
return
@ -574,8 +580,9 @@ export default {
let today = new Date()
this.newEstimate.estimate_date = moment(today).toString()
this.newEstimate.expiry_date = moment(today).add(7, 'days').toString()
this.newEstimate.estimate_number = response.data.nextEstimateNumber
this.itemList = response.data.items
this.estimatePrefix = response.data.estimate_prefix
this.estimateNumAttribute = response.data.nextEstimateNumberAttribute
}
this.initLoading = false
},
@ -604,6 +611,7 @@ export default {
}
this.isLoading = true
this.newEstimate.estimate_number = this.estimatePrefix + '-' + this.estimateNumAttribute
let data = {
...this.newEstimate,
@ -637,7 +645,11 @@ export default {
this.isLoading = false
}).catch((err) => {
this.isLoading = false
console.log(err)
if (err.response.data.errors.estimate_number) {
window.toastr['error'](err.response.data.errors.estimate_number)
return true
}
window.toastr['error'](err.response.data.message)
})
},
submitUpdate (data) {
@ -650,7 +662,11 @@ export default {
this.isLoading = false
}).catch((err) => {
this.isLoading = false
console.log(err)
if (err.response.data.errors.estimate_number) {
window.toastr['error'](err.response.data.errors.estimate_number)
return true
}
window.toastr['error'](err.response.data.message)
})
},
checkItemsData (index, isValid) {

View File

@ -36,7 +36,7 @@
<base-input
v-model="item.quantity"
:invalid="$v.item.quantity.$error"
type="number"
type="text"
small
@keyup="updateItem"
@input="$v.item.quantity.$touch()"
@ -353,7 +353,7 @@ export default {
this.item.name = val
},
deselectItem () {
this.item = {...EstimateStub, id: this.item.id}
this.item = {...EstimateStub, id: this.item.id, taxes: [{...TaxStub, id: Guid.raw()}]}
this.$nextTick(() => {
this.$refs.itemSelect.$refs.baseSelect.$refs.search.focus()
})

View File

@ -151,6 +151,7 @@ export default {
id: null,
count: null,
estimates: [],
estimate: null,
currency: null,
searchData: {
orderBy: null,
@ -165,10 +166,6 @@ export default {
}
},
computed: {
estimate () {
return this.$store.getters['estimate/getEstimate'](this.$route.params.id)
},
getOrderBy () {
if (this.searchData.orderBy === 'asc' || this.searchData.orderBy == null) {
return true
@ -180,8 +177,14 @@ export default {
return `/estimates/pdf/${this.estimate.unique_hash}`
}
},
watch: {
$route (to, from) {
this.loadEstimate()
}
},
created () {
this.loadEstimates()
this.loadEstimate()
this.onSearched = _.debounce(this.onSearched, 500)
},
methods: {
@ -192,7 +195,8 @@ export default {
'markAsSent',
'sendEmail',
'deleteEstimate',
'selectEstimate'
'selectEstimate',
'fetchViewEstimate'
]),
async loadEstimates () {
let response = await this.fetchEstimates()
@ -200,6 +204,13 @@ export default {
this.estimates = response.data.estimates.data
}
},
async loadEstimate () {
let response = await this.fetchViewEstimate(this.$route.params.id)
if (response.data) {
this.estimate = response.data.estimate
}
},
async onSearched () {
let data = ''
if (this.searchData.searchText !== '' && this.searchData.searchText !== null && this.searchData.searchText !== undefined) {

View File

@ -30,8 +30,8 @@
<div
v-if="selectedCustomer" class="show-customer">
<div class="row px-2 mt-1">
<div class="col col-6">
<div v-if="selectedCustomer.billing_address" class="row address-menu">
<div v-if="selectedCustomer.billing_address" class="col col-6">
<div class="row address-menu">
<label class="col-sm-4 px-2 title">{{ $t('general.bill_to') }}</label>
<div class="col-sm p-0 px-2 content">
<label v-if="selectedCustomer.billing_address.name">
@ -44,7 +44,7 @@
{{ selectedCustomer.billing_address.address_street_2 }}
</label>
<label v-if="selectedCustomer.billing_address.city && selectedCustomer.billing_address.state">
{{ selectedCustomer.billing_address.city.name }}, {{ selectedCustomer.billing_address.state.name }} {{ selectedCustomer.billing_address.zip }}
{{ selectedCustomer.billing_address.city }}, {{ selectedCustomer.billing_address.state }} {{ selectedCustomer.billing_address.zip }}
</label>
<label v-if="selectedCustomer.billing_address.country">
{{ selectedCustomer.billing_address.country.name }}
@ -55,8 +55,8 @@
</div>
</div>
</div>
<div class="col col-6">
<div v-if="selectedCustomer.shipping_address" class="row address-menu">
<div v-if="selectedCustomer.shipping_address" class="col col-6">
<div class="row address-menu">
<label class="col-sm-4 px-2 title">{{ $t('general.ship_to') }}</label>
<div class="col-sm p-0 px-2 content">
<label v-if="selectedCustomer.shipping_address.name">
@ -69,7 +69,7 @@
{{ selectedCustomer.shipping_address.address_street_2 }}
</label>
<label v-if="selectedCustomer.shipping_address.city && selectedCustomer.shipping_address">
{{ selectedCustomer.shipping_address.city.name }}, {{ selectedCustomer.shipping_address.state.name }} {{ selectedCustomer.shipping_address.zip }}
{{ selectedCustomer.shipping_address.city }}, {{ selectedCustomer.shipping_address.state }} {{ selectedCustomer.shipping_address.zip }}
</label>
<label v-if="selectedCustomer.shipping_address.country" class="country">
{{ selectedCustomer.shipping_address.country.name }}
@ -127,14 +127,15 @@
<div class="row mt-4">
<div class="col collapse-input">
<label>{{ $t('invoices.invoice_number') }}<span class="text-danger"> * </span></label>
<base-input
:invalid="$v.newInvoice.invoice_number.$error"
:read-only="true"
v-model="newInvoice.invoice_number"
<base-prefix-input
v-model="invoiceNumAttribute"
:invalid="$v.invoiceNumAttribute.$error"
:prefix="invoicePrefix"
icon="hashtag"
@input="$v.newInvoice.invoice_number.$touch()"
@input="$v.invoiceNumAttribute.$touch()"
/>
<span v-show="$v.newInvoice.invoice_number.$error && !$v.newInvoice.invoice_number.required" class="text-danger mt-1"> {{ $tc('validation.required') }} </span>
<span v-show="$v.invoiceNumAttribute.$error && !$v.invoiceNumAttribute.required" class="text-danger mt-1"> {{ $tc('validation.required') }} </span>
<span v-show="!$v.invoiceNumAttribute.numeric" class="text-danger mt-1"> {{ $tc('validation.numbers_only') }} </span>
</div>
<div class="col collapse-input">
<label>{{ $t('invoices.ref_number') }}</label>
@ -320,7 +321,7 @@ import { validationMixin } from 'vuelidate'
import Guid from 'guid'
import TaxStub from '../../stub/tax'
import Tax from './InvoiceTax'
const { required, between, maxLength } = require('vuelidate/lib/validators')
const { required, between, maxLength, numeric } = require('vuelidate/lib/validators')
export default {
components: {
@ -361,7 +362,9 @@ export default {
discountPerItem: null,
initLoading: false,
isLoading: false,
maxDiscount: 0
maxDiscount: 0,
invoicePrefix: null,
invoiceNumAttribute: null
}
},
validations () {
@ -373,9 +376,6 @@ export default {
due_date: {
required
},
invoice_number: {
required
},
discount_val: {
between: between(0, this.subtotal)
},
@ -388,6 +388,10 @@ export default {
},
selectedCustomer: {
required
},
invoiceNumAttribute: {
required,
numeric
}
}
},
@ -559,6 +563,8 @@ export default {
this.taxPerItem = response.data.tax_per_item
this.selectedCurrency = this.defaultCurrency
this.invoiceTemplates = response.data.invoiceTemplates
this.invoicePrefix = response.data.invoice_prefix
this.invoiceNumAttribute = response.data.nextInvoiceNumber
}
this.initLoading = false
return
@ -574,8 +580,9 @@ export default {
let today = new Date()
this.newInvoice.invoice_date = moment(today).toString()
this.newInvoice.due_date = moment(today).add(7, 'days').toString()
this.newInvoice.invoice_number = response.data.nextInvoiceNumber
this.itemList = response.data.items
this.invoicePrefix = response.data.invoice_prefix
this.invoiceNumAttribute = response.data.nextInvoiceNumberAttribute
}
this.initLoading = false
},
@ -604,6 +611,7 @@ export default {
}
this.isLoading = true
this.newInvoice.invoice_number = this.invoicePrefix + '-' + this.invoiceNumAttribute
let data = {
...this.newInvoice,
@ -637,6 +645,10 @@ export default {
this.isLoading = false
}).catch((err) => {
this.isLoading = false
if (err.response.data.errors.invoice_number) {
window.toastr['error'](err.response.data.errors.invoice_number)
return true
}
console.log(err)
})
},
@ -653,6 +665,10 @@ export default {
}
}).catch((err) => {
this.isLoading = false
if (err.response.data.errors.invoice_number) {
window.toastr['error'](err.response.data.errors.invoice_number)
return true
}
console.log(err)
})
},

View File

@ -36,7 +36,7 @@
<base-input
v-model="item.quantity"
:invalid="$v.item.quantity.$error"
type="number"
type="text"
small
@keyup="updateItem"
@input="$v.item.quantity.$touch()"
@ -354,7 +354,7 @@ export default {
this.item.name = val
},
deselectItem () {
this.item = {...InvoiceStub, id: this.item.id}
this.item = {...InvoiceStub, id: this.item.id, taxes: [{...TaxStub, id: Guid.raw()}]}
this.$nextTick(() => {
this.$refs.itemSelect.$refs.baseSelect.$refs.search.focus()
})

View File

@ -154,6 +154,7 @@ export default {
id: null,
count: null,
invoices: [],
invoice: null,
currency: null,
searchData: {
orderBy: null,
@ -167,9 +168,7 @@ export default {
}
},
computed: {
invoice () {
return this.$store.getters['invoice/getInvoice'](this.$route.params.id)
},
getOrderBy () {
if (this.searchData.orderBy === 'asc' || this.searchData.orderBy == null) {
return true
@ -180,8 +179,14 @@ export default {
return `/invoices/pdf/${this.invoice.unique_hash}`
}
},
watch: {
$route (to, from) {
this.loadInvoice()
}
},
created () {
this.loadInvoices()
this.loadInvoice()
this.onSearch = _.debounce(this.onSearch, 500)
},
methods: {
@ -192,7 +197,8 @@ export default {
'markAsSent',
'sendEmail',
'deleteInvoice',
'selectInvoice'
'selectInvoice',
'fetchViewInvoice'
]),
async loadInvoices () {
let response = await this.fetchInvoices()
@ -200,6 +206,13 @@ export default {
this.invoices = response.data.invoices.data
}
},
async loadInvoice () {
let response = await this.fetchViewInvoice(this.$route.params.id)
if (response.data) {
this.invoice = response.data.invoice
}
},
async onSearch () {
let data = ''
if (this.searchData.searchText !== '' && this.searchData.searchText !== null && this.searchData.searchText !== undefined) {
@ -286,7 +299,7 @@ export default {
let request = await this.deleteInvoice(this.id)
if (request.data.success) {
window.toastr['success'](this.$tc('invoices.deleted_message', 1))
this.$router.push('/admin/invoices/')
this.$router.push('/admin/invoices')
} else if (request.data.error) {
window.toastr['error'](request.data.message)
}

View File

@ -50,7 +50,7 @@ export default {
Layout.set('layout-default')
},
created() {
created () {
this.bootstrap().then((res) => {
this.setInitialCompany()
})
@ -59,7 +59,7 @@ export default {
methods: {
...mapActions(['bootstrap']),
...mapActions('company', ['setSelectedCompany']),
setInitialCompany() {
setInitialCompany () {
let selectedCompany = Ls.get('selectedCompany') !== null
if (selectedCompany) {

View File

@ -58,7 +58,7 @@
aria-expanded="false"
class="avatar"
>
<img src="/images/avatar.png" alt="Avatar">
<img :src="profilePicture" alt="Avatar">
</a>
<v-dropdown-item>
<router-link class="dropdown-item" to="/admin/settings">
@ -83,7 +83,25 @@
import { mapGetters, mapActions } from 'vuex'
export default {
computed: {
...mapGetters('userProfile', [
'user'
]),
profilePicture () {
if (this.user && this.user.avatar !== null) {
return this.user.avatar
} else {
return '/images/default-avatar.jpg'
}
}
},
created () {
this.loadData()
},
methods: {
...mapActions('userProfile', [
'loadData'
]),
...mapActions({
companySelect: 'changeCompany'
}),

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