Compare commits

..

41 Commits

Author SHA1 Message Date
cba602655d Converted <label> in <BaseLabel> 2023-03-23 17:24:03 +05:30
87495e8055 added dark-mode in BaseInputGroup and BaseLabel 2023-03-22 10:16:06 +05:30
15f3f566e3 Dark sidebar header (#1156)
* add dark mode in sidebar and header

* add dark theme in blade file
2023-03-20 15:50:27 +05:30
98196194e2 Merge branch 'master' of https://github.com/bytefury/crater 2022-12-13 11:38:49 +05:30
7447cc24f9 feat: uffizzi integration (#1091)
Co-authored-by: Aramayis <>
2022-11-21 18:35:59 +05:30
889d22d92c Update php version (#1083)
Version 7.4 no longer works when running docker-compose/setup.sh. Updated to 8.1 in Dockerfile. Issue is now resolved and Crater sets up as expected without version conflicts.
2022-11-03 19:29:16 +05:30
bc8f2cd484 fix tax issue (#953)
* fix tax issue

* remove console log

* update cs fixer package
2022-10-26 19:51:36 +05:30
4e47f58bad fixed - No query results for model [Crater\Models\Currency] (#1070)
* fixed report pdf issue

* Removed telescope service provider file
2022-10-26 19:33:25 +05:30
d8c429912e fix composer issue with pest 2022-10-17 13:04:27 +05:30
df04fd9e53 Merge branch 'master' of https://github.com/bytefury/crater 2022-10-17 12:48:24 +05:30
0aaf0e7e75 Adding object-fit rules so thumbnail image does not appear stretched. (#1065) 2022-10-13 23:44:39 +05:30
3d0b89bb4d bug: fix missing hyphen in setup.sh (#1067)
Co-authored-by: Aramayis <>
2022-10-13 23:40:07 +05:30
38c4b9ebce Patch setup.sh script to deploy without plugins error. (#1034) 2022-09-13 14:52:51 +05:30
7be59e78e0 Formatting + Netherlands rename (#973)
* Formatting + Netherlands rename

* Revert change
2022-07-09 20:03:08 +05:30
189c51cdf4 Merge branch 'master' of https://github.com/bytefury/crater 2022-06-15 20:39:16 +05:30
204483836a 🌐Update: support Thai language (#768)
* add thai language config

* update thai translation

* update thai translation

* add THSarabunNew fonts to using in pdf

* update: pdf file to support thai language by checking isLocale('th') and include thai font-family

* update: thai translation

* remove the index.php file (not used)

* move THSarabunNew fonts to resoureces/static/fonts

* Add .gitkeep to storage/fonts to pre-build the fonts directory

Co-authored-by: Ritthikrai (Champ) Wiengchai <ritthikrai.w@aware.co.th>
2022-06-15 18:17:36 +05:30
33bc9ded65 Bump guzzlehttp/guzzle from 7.4.1 to 7.4.3 (#936)
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.4.1 to 7.4.3.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/master/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.4.1...7.4.3)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-05 14:10:27 +05:30
4271ef451e Php 8 compliant (#914) 2022-06-05 14:09:42 +05:30
6eb44fba93 Update cron.dockerfile (#949) 2022-06-05 14:09:11 +05:30
96e7300583 Make unit clearable (#918) 2022-05-28 11:55:09 +05:30
a479d966d1 Update en.json (#925)
Corrected sentence case from "Expiry date" to "Expiry Date"
2022-05-28 11:54:32 +05:30
bd5f0fe5cf Merge branch 'v-calendar' into 'master'
apply v-calendar

See merge request mohit.panjvani/crater-web!1468
2022-04-01 10:24:57 +00:00
787619b907 add v-calendar 2022-04-01 10:24:56 +00:00
fd70ab9a99 Merge branch 'fix-expense-receipt-delete-issue' into 'master'
Fix expense receipt delete issue while update

See merge request mohit.panjvani/crater-web!1477
2022-04-01 10:24:20 +00:00
33315638df Fix expense receipt delete issue while update 2022-04-01 15:51:12 +05:30
bba14bf51a Merge branch 'master' 2022-04-01 12:04:06 +05:30
ea41989034 Merge branch 'fix-expense-receipt-issue' into 'master'
fix expense receipt issue

See merge request mohit.panjvani/crater-web!1473
2022-03-30 09:02:56 +00:00
3f3f83a00a fix expense receipt issue 2022-03-30 09:02:56 +00:00
adc5962071 Merge branch 'fix-invoice-status-issue' into 'master'
Fix invoice status issue

See merge request mohit.panjvani/crater-web!1470
2022-03-30 07:38:38 +00:00
c4c00002d7 Fix invoice status issue 2022-03-30 07:38:38 +00:00
a7c1e12db6 Merge branch 'new-custom-fields' into 'master'
added "Due Amount, Total Amount and PDF Link" new custom fields

See merge request mohit.panjvani/crater-web!1464
2022-03-30 07:35:53 +00:00
32949d1eec added "Due Amount, Total Amount and PDF Link" new custom fields 2022-03-30 07:35:53 +00:00
7718f77f3d Merge branch 'master' of https://github.com/bytefury/crater 2022-03-29 13:16:03 +05:30
a9e54981bf Merge branch 'fix-minor-issues' into 'master'
Fix minor issues

See merge request mohit.panjvani/crater-web!1469
2022-03-21 06:45:14 +00:00
ef35293f8a update company slug help text 2022-03-21 12:13:05 +05:30
5c63770b6b added unique validation and help text for company slug field 2022-03-21 12:04:17 +05:30
d130e20c92 Merge branch 'fix-default-custom-value' into 'master'
fixed "Custom fields always set to default value"

See merge request mohit.panjvani/crater-web!1471
2022-03-16 06:04:21 +00:00
586fb1ae10 fixed "Custom fields always set to default value" 2022-03-16 11:28:08 +05:30
20c2502e31 added company slug 2022-03-14 17:45:58 +05:30
0e31f85c18 change company currency if it does not have any transaction. 2022-03-14 12:55:38 +05:30
e7301eb7a3 Fix minor issues 2022-03-14 11:54:13 +05:30
126 changed files with 7460 additions and 8948 deletions

162
.github/workflows/uffizzi-build.yml vendored Normal file
View File

@ -0,0 +1,162 @@
name: Build PR Image
on:
pull_request:
types: [opened,synchronize,reopened,closed]
jobs:
build-application:
name: Build and Push `application`
runs-on: ubuntu-latest
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
outputs:
tags: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Generate UUID image name
id: uuid
run: echo "UUID_TAG_APP=$(uuidgen)" >> $GITHUB_ENV
- name: Docker metadata
id: meta
uses: docker/metadata-action@v3
with:
images: registry.uffizzi.com/${{ env.UUID_TAG_APP }}
tags: type=raw,value=60d
- name: Build and Push Image to registry.uffizzi.com ephemeral registry
uses: docker/build-push-action@v2
with:
push: true
context: ./
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
file: ./uffizzi/Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
build-nginx:
name: Build and Push `nginx`
runs-on: ubuntu-latest
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
outputs:
tags: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Generate UUID image name
id: uuid
run: echo "UUID_TAG_NGINX=$(uuidgen)" >> $GITHUB_ENV
- name: Docker metadata
id: meta
uses: docker/metadata-action@v3
with:
images: registry.uffizzi.com/${{ env.UUID_TAG_NGINX }}
tags: type=raw,value=60d
- name: Build and Push Image to Uffizzi ephemeral registry
uses: docker/build-push-action@v2
with:
push: true
context: ./
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
file: ./uffizzi/nginx/Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
build-crond:
name: Build and Push `crond`
runs-on: ubuntu-latest
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
outputs:
tags: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Generate UUID image name
id: uuid
run: echo "UUID_TAG_CROND=$(uuidgen)" >> $GITHUB_ENV
- name: Docker metadata
id: meta
uses: docker/metadata-action@v3
with:
images: registry.uffizzi.com/${{ env.UUID_TAG_CROND }}
tags: type=raw,value=60d
- name: Build and Push Image to registry.uffizzi.com ephemeral registry
uses: docker/build-push-action@v2
with:
push: true
context: ./
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
file: ./uffizzi/crond/Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
render-compose-file:
name: Render Docker Compose File
# Pass output of this workflow to another triggered by `workflow_run` event.
runs-on: ubuntu-latest
outputs:
compose-file-cache-key: ${{ steps.hash.outputs.hash }}
needs:
- build-application
- build-nginx
- build-crond
steps:
- name: Checkout git repo
uses: actions/checkout@v3
- name: Render Compose File
run: |
APP_IMAGE=$(echo ${{ needs.build-application.outputs.tags }})
export APP_IMAGE
NGINX_IMAGE=$(echo ${{ needs.build-nginx.outputs.tags }})
export NGINX_IMAGE
CROND_IMAGE=$(echo ${{ needs.build-crond.outputs.tags }})
export CROND_IMAGE
# Render simple template from environment variables.
envsubst < ./uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml
cat docker-compose.rendered.yml
- name: Upload Rendered Compose File as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: docker-compose.rendered.yml
retention-days: 2
- name: Serialize PR Event to File
run: |
cat << EOF > event.json
${{ toJSON(github.event) }}
EOF
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: event.json
retention-days: 2
delete-preview:
name: Call for Preview Deletion
runs-on: ubuntu-latest
if: ${{ github.event.action == 'closed' }}
steps:
# If this PR is closing, we will not render a compose file nor pass it to the next workflow.
- name: Serialize PR Event to File
run: echo '${{ toJSON(github.event) }}' > event.json
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: event.json
retention-days: 2

84
.github/workflows/uffizzi-preview.yml vendored Normal file
View File

@ -0,0 +1,84 @@
name: Deploy Uffizzi Preview
on:
workflow_run:
workflows:
- "Build PR Image"
types:
- completed
jobs:
cache-compose-file:
name: Cache Compose File
runs-on: ubuntu-latest
outputs:
compose-file-cache-key: ${{ env.COMPOSE_FILE_HASH }}
pr-number: ${{ env.PR_NUMBER }}
steps:
- name: 'Download artifacts'
# Fetch output (zip archive) from the workflow run that triggered this workflow.
uses: actions/github-script@v6
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "preview-spec"
})[0];
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/preview-spec.zip`, Buffer.from(download.data));
- name: 'Unzip artifact'
run: unzip preview-spec.zip
- name: Read Event into ENV
run: |
echo 'EVENT_JSON<<EOF' >> $GITHUB_ENV
cat event.json >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV
- name: Hash Rendered Compose File
id: hash
# If the previous workflow was triggered by a PR close event, we will not have a compose file artifact.
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
run: echo "COMPOSE_FILE_HASH=$(md5sum docker-compose.rendered.yml | awk '{ print $1 }')" >> $GITHUB_ENV
- name: Cache Rendered Compose File
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
uses: actions/cache@v3
with:
path: docker-compose.rendered.yml
key: ${{ env.COMPOSE_FILE_HASH }}
- name: Read PR Number From Event Object
id: pr
run: echo "PR_NUMBER=${{ fromJSON(env.EVENT_JSON).number }}" >> $GITHUB_ENV
- name: DEBUG - Print Job Outputs
if: ${{ runner.debug }}
run: |
echo "PR number: ${{ env.PR_NUMBER }}"
echo "Compose file hash: ${{ env.COMPOSE_FILE_HASH }}"
cat event.json
deploy-uffizzi-preview:
name: Use Remote Workflow to Preview on Uffizzi
needs:
- cache-compose-file
uses: UffizziCloud/preview-action/.github/workflows/reusable.yaml@v2.6.1
with:
# If this workflow was triggered by a PR close event, cache-key will be an empty string
# and this reusable workflow will delete the preview deployment.
compose-file-cache-key: ${{ needs.cache-compose-file.outputs.compose-file-cache-key }}
compose-file-cache-path: docker-compose.rendered.yml
server: https://app.uffizzi.com/
pr-number: ${{ needs.cache-compose-file.outputs.pr-number }}
permissions:
contents: read
pull-requests: write
id-token: write

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ Homestead.yaml
.gitkeep
/public/docs
/.scribe
!storage/fonts/.gitkeep

View File

@ -1,4 +1,4 @@
FROM php:7.4-fpm
FROM php:8.1-fpm
# Arguments defined in docker-compose.yml
ARG user

View File

@ -103,6 +103,7 @@ class CustomerStatsController extends Controller
)
->whereCompany()
->whereCustomer($customer->id)
->where('status', '<>', Invoice::STATUS_DRAFT)
->sum('total');
$totalReceipts = Payment::whereBetween(
'payment_date',

View File

@ -104,6 +104,7 @@ class DashboardController extends Controller
'invoice_date',
[$startDate->format('Y-m-d'), $start->format('Y-m-d')]
)
->where('status', '<>', Invoice::STATUS_DRAFT)
->whereCompany()
->sum('base_total');
@ -141,6 +142,7 @@ class DashboardController extends Controller
$recent_due_invoices = Invoice::with('customer')
->whereCompany()
->where('base_due_amount', '>', 0)
->where('status', '<>', Invoice::STATUS_DRAFT)
->take(5)
->latest()
->get();

View File

@ -24,6 +24,7 @@ class InvoicesController extends Controller
$limit = $request->has('limit') ? $request->limit : 10;
$invoices = Invoice::whereCompany()
->whereTabFilters($request->tab_status)
->join('customers', 'customers.id', '=', 'invoices.customer_id')
->applyFilters($request->all())
->select('invoices.*', 'customers.name')

View File

@ -2,24 +2,25 @@
namespace Crater\Http\Controllers\V1\Admin\Report;
use PDF;
use Carbon\Carbon;
use Crater\Http\Controllers\Controller;
use Crater\Models\Company;
use Crater\Models\CompanySetting;
use Crater\Models\Currency;
use Crater\Models\Customer;
use Illuminate\Http\Request;
use Crater\Models\CompanySetting;
use Illuminate\Support\Facades\App;
use PDF;
use Crater\Http\Controllers\Controller;
class CustomerSalesReportController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request, $hash)
{
$company = Company::where('unique_hash', $hash)->first();
@ -56,6 +57,7 @@ class CustomerSalesReportController extends Controller
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
$colors = [
'primary_text_color',
@ -80,6 +82,7 @@ class CustomerSalesReportController extends Controller
'company' => $company,
'from_date' => $from_date,
'to_date' => $to_date,
'currency' => $currency,
]);
$pdf = PDF::loadView('app.pdf.reports.sales-customers');

View File

@ -2,24 +2,25 @@
namespace Crater\Http\Controllers\V1\Admin\Report;
use Carbon\Carbon;
use Crater\Http\Controllers\Controller;
use Crater\Models\Company;
use Crater\Models\CompanySetting;
use Crater\Models\Expense;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use PDF;
use Carbon\Carbon;
use Crater\Models\Company;
use Crater\Models\Expense;
use Crater\Models\Currency;
use Illuminate\Http\Request;
use Crater\Models\CompanySetting;
use Illuminate\Support\Facades\App;
use Crater\Http\Controllers\Controller;
class ExpensesReportController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request, $hash)
{
$company = Company::where('unique_hash', $hash)->first();
@ -43,6 +44,7 @@ class ExpensesReportController extends Controller
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
$colors = [
'primary_text_color',
@ -66,6 +68,7 @@ class ExpensesReportController extends Controller
'company' => $company,
'from_date' => $from_date,
'to_date' => $to_date,
'currency' => $currency,
]);
$pdf = PDF::loadView('app.pdf.reports.expenses');

View File

@ -2,24 +2,25 @@
namespace Crater\Http\Controllers\V1\Admin\Report;
use Carbon\Carbon;
use Crater\Http\Controllers\Controller;
use Crater\Models\Company;
use Crater\Models\CompanySetting;
use Crater\Models\InvoiceItem;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use PDF;
use Carbon\Carbon;
use Crater\Models\Company;
use Crater\Models\Currency;
use Illuminate\Http\Request;
use Crater\Models\InvoiceItem;
use Crater\Models\CompanySetting;
use Illuminate\Support\Facades\App;
use Crater\Http\Controllers\Controller;
class ItemSalesReportController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request, $hash)
{
$company = Company::where('unique_hash', $hash)->first();
@ -43,6 +44,7 @@ class ItemSalesReportController extends Controller
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
$colors = [
'primary_text_color',
@ -66,6 +68,7 @@ class ItemSalesReportController extends Controller
'company' => $company,
'from_date' => $from_date,
'to_date' => $to_date,
'currency' => $currency,
]);
$pdf = PDF::loadView('app.pdf.reports.sales-items');

View File

@ -2,25 +2,26 @@
namespace Crater\Http\Controllers\V1\Admin\Report;
use PDF;
use Carbon\Carbon;
use Crater\Http\Controllers\Controller;
use Crater\Models\Company;
use Crater\Models\CompanySetting;
use Crater\Models\Expense;
use Crater\Models\Payment;
use Crater\Models\Currency;
use Illuminate\Http\Request;
use Crater\Models\CompanySetting;
use Illuminate\Support\Facades\App;
use PDF;
use Crater\Http\Controllers\Controller;
class ProfitLossReportController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request, $hash)
{
$company = Company::where('unique_hash', $hash)->first();
@ -49,6 +50,8 @@ class ProfitLossReportController extends Controller
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
$colors = [
'primary_text_color',
@ -74,6 +77,7 @@ class ProfitLossReportController extends Controller
'company' => $company,
'from_date' => $from_date,
'to_date' => $to_date,
'currency' => $currency,
]);
$pdf = PDF::loadView('app.pdf.reports.profit-loss');

View File

@ -2,24 +2,25 @@
namespace Crater\Http\Controllers\V1\Admin\Report;
use Carbon\Carbon;
use Crater\Http\Controllers\Controller;
use Crater\Models\Company;
use Crater\Models\CompanySetting;
use Crater\Models\Tax;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use PDF;
use Carbon\Carbon;
use Crater\Models\Tax;
use Crater\Models\Company;
use Crater\Models\Currency;
use Illuminate\Http\Request;
use Crater\Models\CompanySetting;
use Illuminate\Support\Facades\App;
use Crater\Http\Controllers\Controller;
class TaxSummaryReportController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param string $hash
* @return \Illuminate\Http\JsonResponse
*/
public function __invoke(Request $request, $hash)
{
$company = Company::where('unique_hash', $hash)->first();
@ -44,6 +45,8 @@ class TaxSummaryReportController extends Controller
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
$colors = [
'primary_text_color',
@ -68,6 +71,7 @@ class TaxSummaryReportController extends Controller
'company' => $company,
'from_date' => $from_date,
'to_date' => $to_date,
'currency' => $currency,
]);
$pdf = PDF::loadView('app.pdf.reports.tax-summary');

View File

@ -3,7 +3,6 @@
namespace Crater\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class CompaniesRequest extends FormRequest
@ -34,6 +33,10 @@ class CompaniesRequest extends FormRequest
'currency' => [
'required'
],
'slug' => [
'required',
Rule::unique('companies')
],
'address.name' => [
'nullable',
],
@ -68,11 +71,11 @@ class CompaniesRequest extends FormRequest
{
return collect($this->validated())
->only([
'name'
'name',
'slug'
])
->merge([
'owner_id' => $this->user()->id,
'slug' => Str::slug($this->name)
'owner_id' => $this->user()->id
])
->toArray();
}

View File

@ -30,7 +30,8 @@ class CompanyRequest extends FormRequest
Rule::unique('companies')->ignore($this->header('company'), 'id'),
],
'slug' => [
'nullable'
'required',
Rule::unique('companies')->ignore($this->header('company'), 'id'),
],
'address.country_id' => [
'required',

View File

@ -23,7 +23,7 @@ class EstimateResource extends JsonResource
'reference_number' => $this->reference_number,
'tax_per_item' => $this->tax_per_item,
'discount_per_item' => $this->discount_per_item,
'notes' => $this->getNotes(),
'notes' => $this->notes,
'discount' => $this->discount,
'discount_type' => $this->discount_type,
'discount_val' => $this->discount_val,

View File

@ -18,7 +18,7 @@ class PaymentResource extends JsonResource
'id' => $this->id,
'payment_number' => $this->payment_number,
'payment_date' => $this->payment_date,
'notes' => $this->getNotes(),
'notes' => $this->notes,
'amount' => $this->amount,
'unique_hash' => $this->unique_hash,
'invoice_id' => $this->invoice_id,

View File

@ -217,7 +217,7 @@ class Company extends Model implements HasMedia
'estimate_billing_address_format' => $billingAddressFormat,
'payment_company_address_format' => $companyAddressFormat,
'payment_from_customer_address_format' => $paymentFromCustomerAddress,
'currency' => request()->currency ?? 13,
'currency' => request()->currency ?? 1,
'time_zone' => 'Asia/Kolkata',
'language' => 'en',
'fiscal_year' => '1-12',

View File

@ -483,7 +483,8 @@ class Estimate extends Model implements HasMedia
'{ESTIMATE_DATE}' => $this->formattedEstimateDate,
'{ESTIMATE_EXPIRY_DATE}' => $this->formattedExpiryDate,
'{ESTIMATE_NUMBER}' => $this->estimate_number,
'{ESTIMATE_REF_NUMBER}' => $this->reference_number,
'{PDF_LINK}' => $this->estimatePdfUrl,
'{TOTAL_AMOUNT}' => format_money_pdf($this->total, $this->customer->currency)
];
}

View File

@ -240,7 +240,7 @@ class Expense extends Model implements HasMedia
}
if ($request->hasFile('attachment_receipt')) {
$expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts');
$expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local');
}
if ($request->customFields) {
@ -262,12 +262,12 @@ class Expense extends Model implements HasMedia
ExchangeRateLog::addExchangeRateLog($this);
}
if (isset($request->is_attachment_receipt_removed) && (bool) $request->is_attachment_receipt_removed) {
if (isset($request->is_attachment_receipt_removed) && $request->is_attachment_receipt_removed == "true") {
$this->clearMediaCollection('receipts');
}
if ($request->hasFile('attachment_receipt')) {
$this->clearMediaCollection('receipts');
$this->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts');
$this->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local');
}
if ($request->customFields) {

View File

@ -187,16 +187,6 @@ class Invoice extends Model implements HasMedia
return Carbon::parse($this->invoice_date)->format($dateFormat);
}
public function scopeWhereStatus($query, $status)
{
return $query->where('invoices.status', $status);
}
public function scopeWherePaidStatus($query, $status)
{
return $query->where('invoices.paid_status', $status);
}
public function scopeWhereDueStatus($query, $status)
{
return $query->whereIn('invoices.paid_status', [
@ -234,6 +224,40 @@ class Invoice extends Model implements HasMedia
$query->orderBy($orderByField, $orderBy);
}
public function scopeWhereStatus($query, $status)
{
return $query->where('invoices.status', $status);
}
public function scopeWherePaidStatus($query, $status)
{
return $query->where('invoices.paid_status', $status);
}
public function scopeWhereTabFilters($query, $status)
{
if ($status == "DRAFT") {
return $query->where('invoices.status', $status);
}
if ($status == "SENT") {
return $query->whereIn('invoices.status', [
self::STATUS_SENT,
self::STATUS_VIEWED,
self::STATUS_COMPLETED
]);
}
if ($status == 'DUE') {
return $query->whereIn('invoices.paid_status', [
self::STATUS_UNPAID,
self::STATUS_PARTIALLY_PAID,
]);
}
return ;
}
public function scopeApplyFilters($query, array $filters)
{
$filters = collect($filters);
@ -249,17 +273,11 @@ class Invoice extends Model implements HasMedia
$filters->get('status') == self::STATUS_PAID
) {
$query->wherePaidStatus($filters->get('status'));
} elseif ($filters->get('status') == 'DUE') {
$query->whereDueStatus($filters->get('status'));
} else {
$query->whereStatus($filters->get('status'));
}
}
if ($filters->get('paid_status')) {
$query->wherePaidStatus($filters->get('status'));
}
if ($filters->get('invoice_id')) {
$query->whereInvoice($filters->get('invoice_id'));
}
@ -651,7 +669,9 @@ class Invoice extends Model implements HasMedia
'{INVOICE_DATE}' => $this->formattedInvoiceDate,
'{INVOICE_DUE_DATE}' => $this->formattedDueDate,
'{INVOICE_NUMBER}' => $this->invoice_number,
'{INVOICE_REF_NUMBER}' => $this->reference_number,
'{PDF_LINK}' => $this->invoicePdfUrl,
'{DUE_AMOUNT}' => format_money_pdf($this->due_amount, $this->customer->currency),
'{TOTAL_AMOUNT}' => format_money_pdf($this->total, $this->customer->currency)
];
}

View File

@ -435,7 +435,8 @@ class Payment extends Model implements HasMedia
'{PAYMENT_DATE}' => $this->formattedPaymentDate,
'{PAYMENT_MODE}' => $this->paymentMethod ? $this->paymentMethod->name : null,
'{PAYMENT_NUMBER}' => $this->payment_number,
'{PAYMENT_AMOUNT}' => $this->reference_number,
'{PDF_LINK}' => $this->paymentPdfUrl,
'{PAYMENT_AMOUNT}' => format_money_pdf($this->amount, $this->customer->currency)
];
}

View File

@ -38,15 +38,15 @@
"barryvdh/laravel-ide-helper": "^2.6",
"beyondcode/laravel-dump-server": "^1.0",
"facade/ignition": "^2.3.6",
"friendsofphp/php-cs-fixer": "^3.0",
"fzaninotto/faker": "^1.9.1",
"friendsofphp/php-cs-fixer": "^3.8",
"fakerphp/faker": "^1.9.1",
"mockery/mockery": "^1.3.1",
"nunomaduro/collision": "^5.0",
"pestphp/pest": "^1.0",
"pestphp/pest-plugin-faker": "^1.0",
"pestphp/pest-plugin-laravel": "^1.0",
"pestphp/pest-plugin-parallel": "^0.2.1",
"phpunit/phpunit": "^9.0"
"phpunit/phpunit": "^9.3"
},
"autoload": {
"psr-4": {
@ -81,11 +81,14 @@
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"extra": {
"laravel": {
"dont-discover": []
}
}
}
}

2347
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -71,6 +71,7 @@ return [
["code" => "cs", "name" => "Czech"],
["code" => "el", "name" => "Greek"],
["code" => "hr", "name" => "Crotian"],
["code" => "th", "name" => "ไทย"],
],
/*

View File

@ -170,7 +170,7 @@ class CountriesTableSeeder extends Seeder
['id' => 152,'code' => 'NR','name' => "Nauru",'phonecode' => 674],
['id' => 153,'code' => 'NP','name' => "Nepal",'phonecode' => 977],
['id' => 154,'code' => 'AN','name' => "Netherlands Antilles",'phonecode' => 599],
['id' => 155,'code' => 'NL','name' => "Netherlands The",'phonecode' => 31],
['id' => 155,'code' => 'NL','name' => "Netherlands",'phonecode' => 31],
['id' => 156,'code' => 'NC','name' => "New Caledonia",'phonecode' => 687],
['id' => 157,'code' => 'NZ','name' => "New Zealand",'phonecode' => 64],
['id' => 158,'code' => 'NI','name' => "Nicaragua",'phonecode' => 505],

View File

@ -1,7 +1,7 @@
FROM php:7.4-fpm-alpine
FROM php:8.0-fpm-alpine
RUN apk add --no-cache \
php7-bcmath
php8-bcmath
RUN docker-php-ext-install pdo pdo_mysql bcmath

View File

@ -27,7 +27,7 @@
"vite": "^2.6.1"
},
"dependencies": {
"@headlessui/vue": "^1.4.0",
"@headlessui/vue": "^1.5.0",
"@heroicons/vue": "^1.0.1",
"@popperjs/core": "^2.9.2",
"@stripe/stripe-js": "^1.21.2",
@ -48,7 +48,8 @@
"mini-svg-data-uri": "^1.3.3",
"moment": "^2.29.1",
"pinia": "^2.0.4",
"v-money3": "^3.13.5",
"v-calendar": "3.0.0-alpha.8",
"v-money3": "3.16.1",
"v-tooltip": "^4.0.0-alpha.1",
"vue": "^3.2.0-beta.5",
"vue-flatpickr-component": "^9.0.3",

View File

@ -83,25 +83,25 @@
@click="selectNote(index, close)"
>
<div class="flex justify-between px-2">
<label
<BaseLabel
class="
m-0
text-base
font-semibold
leading-tight
text-gray-700
cursor-pointer
!m-0
!text-base
!font-semibold
!leading-tight
!text-gray-700
!cursor-pointer
"
>
{{ note.name }}
</label>
</BaseLabel>
</div>
</div>
</div>
<div v-else class="flex justify-center p-5 text-gray-400">
<label class="text-base text-gray-500">
<BaseLabel class="!text-base !text-gray-500">
{{ $t('general.no_note_found') }}
</label>
</BaseLabel>
</div>
</div>
<button
@ -122,19 +122,18 @@
@click="openNoteModal"
>
<BaseIcon name="CheckCircleIcon" class="text-primary-400" />
<label
<BaseLabel
class="
m-0
ml-3
text-sm
leading-none
cursor-pointer
font-base
text-primary-400
!m-0
!ml-3
!leading-none
!cursor-pointer
!font-base
!text-primary-400
"
>
{{ $t('settings.customization.notes.add_new_note') }}
</label>
</BaseLabel>
</button>
</div>
</PopoverPanel>

View File

@ -64,7 +64,7 @@ function mergeExistingValues() {
if (props.isEdit) {
props.store[props.storeProp].fields.forEach((field) => {
const existingIndex = props.store[props.storeProp].customFields.findIndex(
(f) => f.id === field.custom_field_id
(f) => f.id == field.custom_field_id
)
if (existingIndex > -1) {

View File

@ -9,7 +9,7 @@ import { computed } from 'vue'
const props = defineProps({
modelValue: {
type: String,
default: moment().format('YYYY-MM-DD hh:MM'),
default: moment().format('YYYY-MM-DD HH:mm'),
},
})

View File

@ -17,18 +17,7 @@
<td class="px-5 py-4 text-left align-top">
<div class="flex justify-start">
<div
class="
flex
items-center
justify-center
w-5
h-5
mt-2
text-gray-300
cursor-move
handle
mr-2
"
class="flex items-center justify-center w-5 h-5 mt-2 mr-2 text-gray-300 cursor-move handle"
>
<DragIcon />
</div>
@ -108,7 +97,7 @@
<BaseIcon
name="ChevronDownIcon"
class="w-4 h-4 text-gray-500 ml-1"
class="w-4 h-4 ml-1 text-gray-500"
/>
</span>
</BaseButton>
@ -155,7 +144,7 @@
<BaseContentPlaceholders v-if="loading">
<BaseContentPlaceholdersText
:lines="1"
class="w-24 h-8 rounded-md border"
class="w-24 h-8 border rounded-md"
/>
</BaseContentPlaceholders>
@ -175,6 +164,7 @@
:ability="abilities.CREATE_INVOICE"
:store="store"
:store-prop="storeProp"
:discount="discount"
@update="updateTax"
/>
</td>

View File

@ -1,9 +1,9 @@
<template>
<div class="flex items-center justify-between mb-3">
<div class="flex items-center text-base" style="flex: 4">
<label class="pr-2 mb-0" align="right">
<BaseLabel class="!pr-2 !mb-0" align="right">
{{ $t('invoices.item.tax') }}
</label>
</BaseLabel>
<BaseMultiselect
v-model="selectedTax"
@ -30,25 +30,14 @@
<template v-if="userStore.hasAbilities(ability)" #action>
<button
type="button"
class="
flex
items-center
justify-center
w-full
px-2
cursor-pointer
py-2
bg-gray-200
border-none
outline-none
"
class="flex items-center justify-center w-full px-2 py-2 bg-gray-200 border-none outline-none cursor-pointer "
@click="openTaxModal"
>
<BaseIcon name="CheckCircleIcon" class="h-5 text-primary-400" />
<label
class="ml-2 text-sm leading-none text-primary-400 cursor-pointer"
>{{ $t('invoices.add_new_tax') }}</label
<BaseLabel
class="!ml-2 !leading-none !cursor-pointer !text-primary-400"
>{{ $t('invoices.add_new_tax') }}</BaseLabel
>
</button>
</template>
@ -115,6 +104,10 @@ const props = defineProps({
type: Number,
default: 0,
},
discountedTotal: {
type: Number,
default: 0,
},
currency: {
type: [Object, String],
required: true,
@ -153,19 +146,19 @@ const filteredTypes = computed(() => {
})
const taxAmount = computed(() => {
if (localTax.compound_tax && props.total) {
return ((props.total + props.totalTax) * localTax.percent) / 100
if (localTax.compound_tax && props.discountedTotal) {
return ((props.discountedTotal + props.totalTax) * localTax.percent) / 100
}
if (props.total && localTax.percent) {
return (props.total * localTax.percent) / 100
if (props.discountedTotal && localTax.percent) {
return (props.discountedTotal * localTax.percent) / 100
}
return 0
})
watch(
() => props.total,
() => props.discountedTotal,
() => {
updateRowTax()
}

View File

@ -5,9 +5,9 @@
>
<SelectNotePopup :type="type" @select="onSelectNote" />
</div>
<label class="text-gray-800 font-medium mb-4 text-sm">
<BaseLabel class="!text-gray-800 !mb-4 ">
{{ $t('invoices.notes') }}
</label>
</BaseLabel>
<BaseCustomInput
v-model="store[storeProp].notes"
:content-loading="store.isFetchingInitialSettings"

View File

@ -16,12 +16,12 @@
<BaseContentPlaceholders v-if="isLoading">
<BaseContentPlaceholdersText :lines="1" class="w-16 h-5" />
</BaseContentPlaceholders>
<label
<BaseLabel
v-else
class="text-sm font-semibold leading-5 text-gray-400 uppercase"
class="!font-semibold !text-gray-400 !uppercase"
>
{{ $t('estimates.sub_total') }}
</label>
</BaseLabel>
<BaseContentPlaceholders v-if="isLoading">
<BaseContentPlaceholdersText :lines="1" class="w-16 h-5" />
@ -29,14 +29,7 @@
<label
v-else
class="
flex
items-center
justify-center
m-0
text-lg text-black
uppercase
"
class="flex items-center justify-center m-0 text-lg text-black dark:text-white uppercase "
>
<BaseFormatMoney
:amount="store.getSubTotal"
@ -55,7 +48,7 @@
</BaseContentPlaceholders>
<label
v-else-if="store[storeProp].tax_per_item === 'YES'"
class="m-0 text-sm font-semibold leading-5 text-gray-500 uppercase"
class="m-0 text-sm font-semibold leading-5 text-gray-500 uppercase dark:text-gray-400"
>
{{ tax.name }} - {{ tax.percent }}%
</label>
@ -66,14 +59,7 @@
<label
v-else-if="store[storeProp].tax_per_item === 'YES'"
class="
flex
items-center
justify-center
m-0
text-lg text-black
uppercase
"
class="flex items-center justify-center m-0 text-lg text-black dark:text-white uppercase "
>
<BaseFormatMoney :amount="tax.amount" :currency="defaultCurrency" />
</label>
@ -89,16 +75,16 @@
<BaseContentPlaceholders v-if="isLoading">
<BaseContentPlaceholdersText :lines="1" class="w-16 h-5" />
</BaseContentPlaceholders>
<label
<BaseLabel
v-else
class="text-sm font-semibold leading-5 text-gray-400 uppercase"
class=" !font-semibold !text-gray-400 !uppercase"
>
{{ $t('estimates.discount') }}
</label>
</BaseLabel>
<BaseContentPlaceholders v-if="isLoading">
<BaseContentPlaceholdersText
:lines="1"
class="w-24 h-8 rounded-md border"
class="w-24 h-8 border rounded-md"
/>
</BaseContentPlaceholders>
<div v-else class="flex" style="width: 140px" role="group">
@ -114,7 +100,7 @@
<BaseDropdown position="bottom-end">
<template #activator>
<BaseButton
class="rounded-tr-md rounded-br-md p-2 rounded-none"
class="p-2 rounded-none rounded-tr-md rounded-br-md"
type="button"
variant="white"
>
@ -127,7 +113,7 @@
<BaseIcon
name="ChevronDownIcon"
class="w-4 h-4 text-gray-500 ml-1"
class="w-4 h-4 ml-1 text-gray-500"
/>
</span>
</BaseButton>
@ -180,41 +166,26 @@
</div>
<div
class="
flex
items-center
justify-between
w-full
pt-2
mt-5
border-t border-gray-200 border-solid
"
class="flex items-center justify-between w-full pt-2 mt-5 border-t border-gray-200 border-solid "
>
<BaseContentPlaceholders v-if="isLoading">
<BaseContentPlaceholdersText :lines="1" class="w-16 h-5" />
</BaseContentPlaceholders>
<label
<BaseLabel
v-else
class="m-0 text-sm font-semibold leading-5 text-gray-400 uppercase"
>{{ $t('estimates.total') }} {{ $t('estimates.amount') }}:</label
class="!m-0 !font-semibold !text-gray-400 !uppercase"
>{{ $t('estimates.total') }} {{ $t('estimates.amount') }}:</BaseLabel
>
<BaseContentPlaceholders v-if="isLoading">
<BaseContentPlaceholdersText :lines="1" class="w-16 h-5" />
</BaseContentPlaceholders>
<label
<BaseLabel
v-else
class="
flex
items-center
justify-center
text-lg
uppercase
text-primary-400
"
class="!flex !items-center !justify-center !text-lg !uppercase !text-primary-400"
>
<BaseFormatMoney :amount="store.getTotal" :currency="defaultCurrency" />
</label>
</BaseLabel>
</div>
</div>
</template>
@ -334,6 +305,7 @@ function selectPercentage() {
function onSelectTax(selectedTax) {
let amount = 0
if (selectedTax.compound_tax && props.store.getSubtotalWithDiscount) {
amount = Math.round(
((props.store.getSubtotalWithDiscount + props.store.getTotalSimpleTax) *

View File

@ -1,9 +1,9 @@
<template>
<div class="flex items-center justify-between w-full mt-2 text-sm">
<label class="font-semibold leading-5 text-gray-500 uppercase">
<BaseLabel class="!font-semibold !text-gray-500 !uppercase">
{{ tax.name }} ({{ tax.percent }} %)
</label>
<label class="flex items-center justify-center text-lg text-black">
</BaseLabel>
<label class="flex items-center justify-center text-lg text-black dark:text-white">
<BaseFormatMoney :amount="tax.amount" :currency="currency" />
<BaseIcon

View File

@ -88,38 +88,37 @@
@click="selectTaxType(taxType, close)"
>
<div class="flex justify-between px-2">
<label
<BaseLabel
class="
m-0
text-base
font-semibold
leading-tight
text-gray-700
cursor-pointer
!m-0
!text-base
!font-semibold
!leading-tight
!cursor-pointer
"
>
{{ taxType.name }}
</label>
</BaseLabel>
<label
<BaseLabel
class="
m-0
text-base
font-semibold
text-gray-700
cursor-pointer
!m-0
!text-base
!font-semibold
!text-gray-700
!cursor-pointer
"
>
{{ taxType.percent }} %
</label>
</BaseLabel>
</div>
</div>
</div>
<div v-else class="flex justify-center p-5 text-gray-400">
<label class="text-base text-gray-500 cursor-pointer">
<BaseLabel class="!text-base !text-gray-500 !cursor-pointer">
{{ $t('general.no_tax_found') }}
</label>
</BaseLabel>
</div>
</div>
@ -142,19 +141,18 @@
@click="openTaxTypeModal"
>
<BaseIcon name="CheckCircleIcon" class="text-primary-400" />
<label
<BaseLabel
class="
m-0
ml-3
text-sm
leading-none
cursor-pointer
font-base
text-primary-400
!m-0
!ml-3
!leading-none
!cursor-pointer
!font-base
!text-primary-400
"
>
{{ $t('estimates.add_new_tax') }}
</label>
</BaseLabel>
</button>
</div>
</PopoverPanel>

View File

@ -1,9 +1,9 @@
<template>
<div>
<label class="flex text-gray-800 font-medium text-sm mb-2">
<BaseLabel class="!flex !text-gray-800 !mb-2">
{{ $t('general.select_template') }}
<span class="text-sm text-red-500"> *</span>
</label>
</BaseLabel>
<BaseButton
type="button"
class="flex justify-center w-full text-sm lg:w-auto hover:bg-gray-200"

View File

@ -48,6 +48,24 @@
/>
</BaseInputGroup>
<BaseInputGroup
:label="$tc('settings.company_info.company_slug')"
:help-text="$t('settings.company_info.company_slug_help_text')"
:error="
v$.newCompanyForm.slug.$error &&
v$.newCompanyForm.slug.$errors[0].$message
"
:content-loading="isFetchingInitialData"
required
>
<BaseInput
v-model="newCompanyForm.slug"
:invalid="v$.newCompanyForm.slug.$error"
:content-loading="isFetchingInitialData"
@input="v$.newCompanyForm.slug.$touch()"
/>
</BaseInputGroup>
<BaseInputGroup
:content-loading="isFetchingInitialData"
:label="$tc('settings.company_info.country')"
@ -130,7 +148,7 @@
<script setup>
import { useModalStore } from '@/scripts/stores/modal'
import { computed, onMounted, ref, reactive } from 'vue'
import { computed, onMounted, ref, reactive, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { required, minLength, helpers } from '@vuelidate/validators'
import { useVuelidate } from '@vuelidate/core'
@ -152,6 +170,7 @@ let companyLogoName = ref(null)
const newCompanyForm = reactive({
name: null,
slug: null,
currency: '',
address: {
country_id: null,
@ -162,6 +181,9 @@ const modalActive = computed(() => {
return modalStore.active && modalStore.componentName === 'CompanyModal'
})
const slugValidator = (value) => {
return value == slugify(value)
}
const rules = {
newCompanyForm: {
name: {
@ -171,6 +193,17 @@ const rules = {
minLength(3)
),
},
slug: {
required: helpers.withMessage(t('validation.required'), required),
minLength: helpers.withMessage(
t('validation.name_min_length', { count: 3 }),
minLength(3)
),
slugValidator: helpers.withMessage(
t('validation.invalid_slug'),
slugValidator
),
},
address: {
country_id: {
required: helpers.withMessage(t('validation.required'), required),
@ -243,6 +276,7 @@ async function submitCompanyData() {
function resetNewCompanyForm() {
newCompanyForm.name = ''
newCompanyForm.slug = ''
newCompanyForm.currency = ''
newCompanyForm.address.country_id = ''
@ -257,4 +291,24 @@ function closeCompanyModal() {
v$.value.$reset()
}, 300)
}
// watcher for if change company name then auto fill company slug value
watch(
() => newCompanyForm.name,
(currentValue) => {
newCompanyForm.slug = slugify(currentValue)
}
)
function slugify(string) {
return string
.toString()
.trim()
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^\w\-]+/g, '')
.replace(/\-\-+/g, '-')
.replace(/^-+/, '')
.replace(/-+$/, '')
}
</script>

View File

@ -15,6 +15,13 @@
bg-gradient-to-r
from-primary-500
to-primary-400
dark:from-gray-700/70 dark:to-gray-800/70
bg-primary-500
dark:bg-transparent
dark:backdrop-blur-xl
dark:shadow-glass
dark:border
dark:border-white/10
"
>
<router-link
@ -53,6 +60,7 @@
cursor-pointer
md:hidden md:ml-0
hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-500 dark:border
"
@click.prevent="onToggle"
>
@ -143,7 +151,7 @@
<template #activator>
<img
:src="previewAvatar"
class="block w-8 h-8 rounded md:h-9 md:w-9"
class="block w-8 h-8 rounded md:h-9 md:w-9 object-cover"
/>
</template>

View File

@ -15,7 +15,9 @@
leave-from="opacity-100"
leave-to="opacity-0"
>
<DialogOverlay class="fixed inset-0 bg-gray-600 bg-opacity-75" />
<DialogOverlay
class="fixed inset-0 bg-gray-600 bg-opacity-75 dark:bg-gray-900/90"
/>
</TransitionChild>
<TransitionChild
@ -27,7 +29,9 @@
leave-from="translate-x-0"
leave-to="-translate-x-full"
>
<div class="relative flex flex-col flex-1 w-full max-w-xs bg-white">
<div
class="relative flex flex-col flex-1 w-full max-w-xs bg-white dark:bg-gray-800"
>
<TransitionChild
as="template"
enter="ease-in-out duration-300"
@ -40,18 +44,17 @@
<div class="absolute top-0 right-0 pt-2 -mr-12">
<button
class="
flex
items-center
justify-center
w-10
h-10
ml-1
rounded-full
focus:outline-none
focus:ring-2
focus:ring-inset
focus:ring-white
"
flex
items-center
justify-center
w-10
h-10
ml-1
rounded-full
focus:outline-none
focus:ring-2
focus:ring-inset
focus:ring-white"
@click="globalStore.setSidebarVisibility(false)"
>
<span class="sr-only">Close sidebar</span>
@ -82,8 +85,8 @@
:to="item.link"
:class="[
hasActiveUrl(item.link)
? 'text-primary-500 border-primary-500 bg-gray-100 '
: 'text-black',
? 'text-primary-500 border-primary-500 bg-gray-100 dark:shadow-glass dark:backdrop-blur-xl dark:hover:bg-gray-700 dark:bg-gray-700/50 dark:text-primary-400 dark:font-medium'
: 'text-black dark:text-gray-300',
'cursor-pointer px-0 pl-4 py-3 border-transparent flex items-center border-l-4 border-solid text-sm not-italic font-medium',
]"
@click="globalStore.setSidebarVisibility(false)"
@ -100,6 +103,10 @@
/>
{{ $t(item.title) }}
</router-link>
<LightDarkSwitch
:show-label="false"
class="absolute right-6 top-6 !w-auto"
/>
</nav>
</div>
</div>
@ -113,17 +120,16 @@
<!-- DESKTOP MENU -->
<div
class="
hidden
w-56
h-screen
pb-32
overflow-y-auto
bg-white
border-r border-gray-200 border-solid
xl:w-64
md:fixed md:flex md:flex-col md:inset-y-0
pt-16
"
hidden
w-56
h-screen
bg-white
border-r border-gray-200 border-solid
xl:w-64
md:fixed md:flex md:flex-col md:inset-y-0
pt-16
dark:border-gray-800
dark:bg-gray-800/80"
>
<div
v-for="menu in globalStore.menuGroups"
@ -136,8 +142,8 @@
:to="item.link"
:class="[
hasActiveUrl(item.link)
? 'text-primary-500 border-primary-500 bg-gray-100 '
: 'text-black',
? 'text-primary-500 border-primary-500 bg-gray-100 dark:border-primary-400 dark:shadow-glass dark:backdrop-blur-xl dark:hover:bg-gray-700 dark:bg-gray-700/50 dark:text-primary-400 dark:font-medium'
: 'text-black dark:hover:bg-transparent dark:hover:text-white dark:text-gray-300',
'cursor-pointer px-0 pl-6 hover:bg-gray-50 py-3 group flex items-center border-l-4 border-solid border-transparent text-sm not-italic font-medium',
]"
>
@ -145,8 +151,8 @@
:name="item.icon"
:class="[
hasActiveUrl(item.link)
? 'text-primary-500 group-hover:text-primary-500 '
: 'text-gray-400 group-hover:text-black',
? 'text-primary-500 group-hover:text-primary-500 dark:text-primary-400 dark:group-hover:text-primary-500 '
: 'text-gray-400 group-hover:text-black dark:text-gray-400 dark:group-hover:text-white',
'mr-4 shrink-0 h-5 w-5 ',
]"
/>
@ -154,6 +160,9 @@
{{ $t(item.title) }}
</router-link>
</div>
<LightDarkSwitch
class="absolute bottom-0 py-4 border-t border-gray-200 dark:border-gray-700"
/>
</div>
</template>
@ -169,6 +178,7 @@ import {
import { useRoute } from 'vue-router'
import { useGlobalStore } from '@/scripts/admin/stores/global'
import LightDarkSwitch from '@/scripts/components/LightDarkSwitcher.vue'
const route = useRoute()
const globalStore = useGlobalStore()

View File

@ -184,6 +184,20 @@ export const useCompanyStore = (useWindow = false) => {
setDefaultCurrency(data) {
this.defaultCurrency = data.currency
},
checkCompanyHasCurrencyTransactions() {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/company/has-transactions`)
.then((response) => {
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
},
})()
}

View File

@ -34,6 +34,7 @@ export const useGlobalStore = (useWindow = false) => {
isAppLoaded: false,
isSidebarOpen: false,
areCurrenciesLoading: false,
isDarkModeOn: false,
downloadReport: null,
}),
@ -70,8 +71,8 @@ export const useGlobalStore = (useWindow = false) => {
moduleStore.apiToken = response.data.global_settings.api_token
moduleStore.enableModules = response.data.modules
// company store
companyStore.companies = response.data.companies
// company store
companyStore.companies = response.data.companies
companyStore.selectedCompany = response.data.current_company
companyStore.setSelectedCompany(response.data.current_company)
companyStore.selectedCompanySettings =

View File

@ -32,6 +32,8 @@
:content-loading="isLoading"
:calendar-button="true"
calendar-button-icon="calendar"
:show-extra-options="true"
:source-date="estimateStore.newEstimate.estimate_date"
/>
</BaseInputGroup>

View File

@ -34,6 +34,24 @@
/>
</BaseInputGroup>
<BaseInputGroup
:label="$tc('wizard.company_slug')"
:help-text="$t('wizard.company_slug_help_text')"
:error="
v$.companyForm.slug.$error &&
v$.companyForm.slug.$errors[0].$message
"
required
>
<BaseInput
v-model="companyForm.slug"
:invalid="v$.companyForm.slug.$error"
type="text"
name="slug"
@input="v$.companyForm.slug.$touch()"
/>
</BaseInputGroup>
<BaseInputGroup
:label="$t('wizard.country')"
:error="
@ -57,9 +75,7 @@
track-by="name"
/>
</BaseInputGroup>
</div>
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6">
<BaseInputGroup :label="$t('wizard.state')">
<BaseInput
v-model="companyForm.address.state"
@ -144,9 +160,9 @@
</template>
<script setup>
import { ref, computed, onMounted, reactive } from 'vue'
import { ref, computed, onMounted, reactive, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { required, maxLength, helpers } from '@vuelidate/validators'
import { required, minLength, maxLength, helpers } from '@vuelidate/validators'
import { useVuelidate } from '@vuelidate/core'
import { useGlobalStore } from '@/scripts/admin/stores/global'
import { useCompanyStore } from '@/scripts/admin/stores/company'
@ -162,6 +178,7 @@ let logoFileName = ref(null)
const companyForm = reactive({
name: null,
slug: null,
address: {
address_street_1: '',
address_street_2: '',
@ -188,10 +205,28 @@ onMounted(async () => {
})?.id
})
const slugValidator = (value) => {
return value == slugify(value)
}
const rules = {
companyForm: {
name: {
required: helpers.withMessage(t('validation.required'), required),
minLength: helpers.withMessage(
t('validation.name_min_length', { count: 3 }),
minLength(3)
),
},
slug: {
required: helpers.withMessage(t('validation.required'), required),
minLength: helpers.withMessage(
t('validation.name_min_length', { count: 3 }),
minLength(3)
),
slugValidator: helpers.withMessage(
t('validation.invalid_slug'),
slugValidator
),
},
address: {
country_id: {
@ -249,4 +284,24 @@ async function next() {
emit('next', 7)
}
}
// watcher for if change company name then auto fill company slug value
watch(
() => companyForm.name,
(currentValue) => {
companyForm.slug = slugify(currentValue)
}
)
function slugify(string) {
return string
.toString()
.trim()
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^\w\-]+/g, '')
.replace(/\-\-+/g, '-')
.replace(/^-+/, '')
.replace(/-+$/, '')
}
</script>

View File

@ -56,7 +56,7 @@
<BaseMultiselect
v-model="filters.status"
:groups="true"
:options="status"
:options="invoiceStatus"
searchable
:placeholder="$t('general.select_a_status')"
@update:modelValue="setActiveTab"
@ -130,11 +130,27 @@
"
>
<!-- Tabs -->
<BaseTabGroup class="-mb-5" @change="setStatusFilter">
<BaseTab :title="$t('general.all')" filter="" />
<BaseTab :title="$t('general.draft')" filter="DRAFT" />
<BaseTab :title="$t('general.sent')" filter="SENT" />
<BaseTab :title="$t('general.due')" filter="DUE" />
<BaseTabGroup
class="-mb-5"
:selected-index="selectedIndex"
@change="changeTabStatus"
>
<BaseTab
:title="invoiceTabStatus[0].title"
:tab-status="invoiceTabStatus[0].value"
/>
<BaseTab
:title="invoiceTabStatus[1].title"
:tab-status="invoiceTabStatus[1].value"
/>
<BaseTab
:title="invoiceTabStatus[2].title"
:tab-status="invoiceTabStatus[2].value"
/>
<BaseTab
:title="invoiceTabStatus[3].title"
:tab-status="invoiceTabStatus[3].value"
/>
</BaseTabGroup>
<BaseDropdown
@ -289,10 +305,10 @@ const utils = inject('$utils')
const table = ref(null)
const showFilters = ref(false)
const status = ref([
const invoiceStatus = ref([
{
label: 'Status',
options: ['DRAFT', 'DUE', 'SENT', 'VIEWED', 'COMPLETED'],
options: ['DRAFT', 'SENT', 'VIEWED', 'COMPLETED'],
},
{
label: 'Paid Status',
@ -300,10 +316,29 @@ const status = ref([
},
,
])
const invoiceTabStatus = {
0: {
title: t('general.all'),
value: '',
},
1: {
title: t('general.draft'),
value: 'DRAFT',
},
2: {
title: t('general.sent'),
value: 'SENT',
},
3: {
title: t('general.due'),
value: 'DUE',
},
}
const isRequestOngoing = ref(true)
const activeTab = ref('general.draft')
const router = useRouter()
const userStore = useUserStore()
const selectedIndex = ref(0)
let filters = reactive({
customer_id: '',
@ -311,6 +346,7 @@ let filters = reactive({
from_date: '',
to_date: '',
invoice_number: '',
tab_status: '',
})
const showEmptyScreen = computed(
@ -401,6 +437,7 @@ async function fetchData({ page, filter, sort }) {
from_date: filters.from_date,
to_date: filters.to_date,
invoice_number: filters.invoice_number,
tab_status: filters.tab_status,
orderByField: sort.fieldName || 'created_at',
orderBy: sort.order || 'desc',
page,
@ -423,29 +460,9 @@ async function fetchData({ page, filter, sort }) {
}
}
function setStatusFilter(val) {
if (activeTab.value == val.title) {
return true
}
activeTab.value = val.title
switch (val.title) {
case t('general.draft'):
filters.status = 'DRAFT'
break
case t('general.sent'):
filters.status = 'SENT'
break
case t('general.due'):
filters.status = 'DUE'
break
default:
filters.status = ''
break
}
function changeTabStatus(val, index) {
filters.tab_status = val['tab-status']
selectedIndex.value = index
}
function setFilters() {
@ -463,8 +480,6 @@ function clearFilter() {
filters.from_date = ''
filters.to_date = ''
filters.invoice_number = ''
activeTab.value = t('general.all')
}
async function removeMultipleInvoices() {
@ -505,39 +520,21 @@ function toggleFilter() {
function setActiveTab(val) {
switch (val) {
case 'DRAFT':
activeTab.value = t('general.draft')
selectedIndex.value = 1
break
case 'SENT':
activeTab.value = t('general.sent')
break
case 'DUE':
activeTab.value = t('general.due')
break
case 'VIEWED':
case 'COMPLETED':
activeTab.value = t('invoices.completed')
break
case 'PAID':
activeTab.value = t('invoices.paid')
selectedIndex.value = 2
break
case 'UNPAID':
activeTab.value = t('invoices.unpaid')
break
case 'PARTIALLY_PAID':
activeTab.value = t('invoices.partially_paid')
break
case 'VIEWED':
activeTab.value = t('invoices.viewed')
break
default:
activeTab.value = t('general.all')
selectedIndex.value = 3
break
}
filters.tab_status = invoiceTabStatus[selectedIndex.value].value
}
</script>

View File

@ -32,6 +32,8 @@
:content-loading="isLoading"
:calendar-button="true"
calendar-button-icon="calendar"
:show-extra-options="true"
:source-date="invoiceStore.newInvoice.invoice_date"
/>
</BaseInputGroup>

View File

@ -54,8 +54,6 @@
label="name"
:options="itemStore.itemUnits"
value-prop="id"
:can-deselect="false"
:can-clear="false"
:placeholder="$t('items.select_a_unit')"
searchable
track-by="name"

View File

@ -53,7 +53,7 @@
</div>
</div>
<div v-else class="mt-24">
<label class="flex items-center justify-center text-gray-500">
<label class="flex items-center justify-center text-gray-500 dark:text-gray-300">
{{ $t('modules.no_modules_installed') }}
</label>
</div>

View File

@ -82,9 +82,9 @@
required
>
<BaseCustomerSelectInput
v-if="!isLoadingContent"
v-model="paymentStore.currentPayment.customer_id"
:content-loading="isLoadingContent"
v-if="!isLoadingContent"
:invalid="v$.currentPayment.customer_id.$error"
:placeholder="$t('customers.select_a_customer')"
show-action
@ -215,9 +215,9 @@
<SelectNotePopup type="Payment" @select="onSelectNote" />
</div>
<label class="mb-4 text-sm font-medium text-gray-800">
<BaseLabel class="!mb-4 !text-gray-800">
{{ $t('estimates.notes') }}
</label>
</BaseLabel>
<BaseCustomInput
v-model="paymentStore.currentPayment.notes"
@ -423,7 +423,7 @@ function onCustomerChange(customer_id) {
if (customer_id) {
let data = {
customer_id: customer_id,
status: 'DUE',
tab_status: 'DUE',
limit: 'all',
}
@ -446,7 +446,11 @@ function onCustomerChange(customer_id) {
paymentStore.currentPayment.selectedCustomer = res2.data.data
paymentStore.currentPayment.customer = res2.data.data
paymentStore.currentPayment.currency = res2.data.data.currency
if(isEdit.value && !customerStore.editCustomer && paymentStore.currentPayment.customer_id) {
if (
isEdit.value &&
!customerStore.editCustomer &&
paymentStore.currentPayment.customer_id
) {
customerStore.editCustomer = res2.data.data
}
}

View File

@ -28,6 +28,19 @@
/>
</BaseInputGroup>
<BaseInputGroup
:label="$tc('settings.company_info.company_slug')"
:help-text="$t('settings.company_info.company_slug_help_text')"
:error="v$.slug.$error && v$.slug.$errors[0].$message"
required
>
<BaseInput
v-model="companyForm.slug"
:invalid="v$.slug.$error"
@blur="v$.slug.$touch()"
/>
</BaseInputGroup>
<BaseInputGroup :label="$tc('settings.company_info.phone')">
<BaseInput v-model="companyForm.address.phone" />
</BaseInputGroup>
@ -160,6 +173,7 @@ let isSaving = ref(false)
const companyForm = reactive({
name: null,
slug: null,
logo: null,
address: {
address_street_1: '',
@ -193,7 +207,14 @@ const rules = computed(() => {
name: {
required: helpers.withMessage(t('validation.required'), required),
minLength: helpers.withMessage(
t('validation.name_min_length'),
t('validation.name_min_length', { count: 3 }),
minLength(3)
),
},
slug: {
required: helpers.withMessage(t('validation.required'), required),
minLength: helpers.withMessage(
t('validation.name_min_length', { count: 3 }),
minLength(3)
),
},

View File

@ -8,7 +8,11 @@
<BaseInputGroup
:content-loading="isFetchingInitialData"
:label="$tc('settings.preferences.currency')"
:help-text="$t('settings.preferences.company_currency_unchangeable')"
:help-text="
isCurrencyDisabled
? $t('settings.preferences.company_currency_unchangeable')
: ''
"
:error="v$.currency.$error && v$.currency.$errors[0].$message"
required
>
@ -21,7 +25,7 @@
:searchable="true"
track-by="name"
:invalid="v$.currency.$error"
disabled
:disabled="isCurrencyDisabled"
class="w-full"
>
</BaseMultiselect>
@ -187,6 +191,7 @@ const { t, tm } = useI18n()
let isSaving = ref(false)
let isDataSaving = ref(false)
let isFetchingInitialData = ref(false)
let isCurrencyDisabled = ref(true)
const settingsForm = reactive({ ...companyStore.selectedCompanySettings })
@ -282,10 +287,14 @@ setInitialData()
async function setInitialData() {
isFetchingInitialData.value = true
Promise.all([
companyStore.checkCompanyHasCurrencyTransactions(),
globalStore.fetchCurrencies(),
globalStore.fetchDateFormats(),
globalStore.fetchTimeZones(),
]).then(([res1]) => {
if (res1.data?.has_transactions == false) {
isCurrencyDisabled.value = false
}
isFetchingInitialData.value = false
})
}

View File

@ -4,9 +4,9 @@
:description="$t('settings.update_app.description')"
>
<div class="pb-8 ml-0">
<label class="text-sm not-italic font-medium input-label">
<BaseLabel class="!input-label">
{{ $t('settings.update_app.current_version') }}
</label>
</BaseLabel>
<div
class="
@ -64,9 +64,9 @@
</div>
</div>
<label class="text-sm not-italic font-medium input-label">
<BaseLabel class="!input-label">
{{ $t('settings.update_app.next_version') }}
</label>
</BaseLabel>
<br />
<div
class="
@ -99,9 +99,9 @@
v-html="description"
></div>
<label class="text-sm not-italic font-medium input-label">
<BaseLabel class=" !input-label">
{{ $t('settings.update_app.requirements') }}
</label>
</BaseLabel>
<table class="w-1/2 mt-2 border-2 border-gray-200 BaseTable-fixed">
<tr

View File

@ -97,6 +97,7 @@
whitespace-nowrap
mr-2
min-w-[200px]
dark:text-primary-400
"
>
{{ element.label }}

View File

@ -50,20 +50,20 @@
pb-4
"
>
<label
<BaseLabel
class="
px-3
py-2
text-xs
font-semibold
text-gray-400
mb-0.5
block
uppercase
!px-3
!py-2
!text-xs
!font-semibold
!text-gray-400
!mb-0.5
!block
!uppercase
"
>
{{ $t('company_switcher.label') }}
</label>
</BaseLabel>
<div
v-if="companyStore.companies.length < 1"

View File

@ -62,9 +62,9 @@
</div>
<div v-else>
<div v-if="usersStore.customerList.length > 0">
<label class="text-sm text-gray-400 mb-0.5 block px-2 uppercase">
<BaseLabel class="!text-gray-400 !mb-0.5 !block !px-2 !uppercase">
{{ $t('global_search.customers') }}
</label>
</BaseLabel>
<div
v-for="(customer, index) in usersStore.customerList"
:key="index"
@ -108,11 +108,11 @@
</div>
<div v-if="usersStore.userList.length > 0" class="mt-2">
<label
class="text-sm text-gray-400 mb-2 block px-2 mb-0.5 uppercase"
<BaseLabel
class="!text-gray-400 !mb-2 !block !px-2 !uppercase"
>
{{ $t('global_search.users') }}
</label>
</BaseLabel>
<div
v-for="(user, index) in usersStore.userList"
:key="index"

View File

@ -0,0 +1,101 @@
<!-- This example requires Tailwind CSS v2.0+ -->
<script lang="ts" setup>
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue'
import { useGlobalStore } from '@/scripts/admin/stores/global'
import { computed, ref } from 'vue'
defineProps({
showLabel: {
type: Boolean,
default: true,
},
vertical: {
type: Boolean,
default: false,
},
})
const globalStore = useGlobalStore()
const enabled = ref(
localStorage.getItem('theme') === 'dark' ||
document.documentElement.classList.contains('dark')
)
globalStore.isDarkModeOn = enabled
function onChange(val) {
if (val) {
localStorage.theme = 'dark'
document.documentElement.classList.add('dark')
document.documentElement.style.setProperty('color-scheme', 'dark')
globalStore.isDarkModeOn = true
} else {
localStorage.theme = 'light'
document.documentElement.classList.remove('dark')
document.documentElement.style.setProperty('color-scheme', 'light')
globalStore.isDarkModeOn = false
}
}
</script>
<template>
<div class="w-full flex justify-center">
<SwitchGroup
as="div"
class="flex items-center"
:class="vertical ? 'flex-col justify-center' : 'flex-row'"
>
<Switch
v-model="enabled"
class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 dark:ring-offset-gray-700"
:class="[enabled ? 'bg-primary-600' : 'bg-gray-200']"
@update:modelValue="onChange"
>
<span class="sr-only">Use setting</span>
<span
class="pointer-events-none relative inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"
:class="[enabled ? 'translate-x-5' : 'translate-x-0']"
>
<span
class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity"
:class="[
enabled
? 'opacity-0 ease-out duration-100'
: 'opacity-100 ease-in duration-200',
]"
aria-hidden="true"
>
<BaseIcon class="h-3 w-3 text-yellow-500" name="SunIcon" />
</span>
<span
class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity"
:class="[
enabled
? 'opacity-100 ease-in duration-200'
: 'opacity-0 ease-out duration-100',
]"
aria-hidden="true"
>
<BaseIcon class="h-3 w-3 text-primary-500" name="MoonIcon" />
</span>
</span>
</Switch>
<SwitchLabel
v-if="showLabel"
as="span"
class="cursor-pointer"
:class="vertical ? 'px-1 text-center mt-2' : 'ml-3'"
>
<span
v-if="enabled"
class="text-sm font-medium text-gray-500 dark:text-gray-400"
>
Dark Mode
</span>
<span v-else class="text-sm font-medium text-gray-500">
Light Mode
</span>
</SwitchLabel>
</SwitchGroup>
</div>
</template>

View File

@ -15,7 +15,7 @@
v-if="label"
:for="id"
:class="`font-medium ${
disabled ? 'text-gray-400 cursor-not-allowed' : 'text-gray-600'
disabled ? 'text-gray-400 cursor-not-allowed' : 'text-gray-600 dark:text-white'
} cursor-pointer `"
>
{{ label }}

View File

@ -126,7 +126,7 @@ onMounted(() => {
})
const value = computed({
get: () => props.modelValue,
get: () => (props.modelValue ? props.modelValue : ''),
set: (value) => {
emit('update:modelValue', value)
},
@ -195,7 +195,9 @@ async function getFields() {
{ label: 'Date', value: 'INVOICE_DATE' },
{ label: 'Due Date', value: 'INVOICE_DUE_DATE' },
{ label: 'Number', value: 'INVOICE_NUMBER' },
{ label: 'Ref Number', value: 'INVOICE_REF_NUMBER' },
{ label: 'PDF Link', value: 'PDF_LINK' },
{ label: 'Due Amount', value: 'DUE_AMOUNT' },
{ label: 'Total Amount', value: 'TOTAL_AMOUNT' },
...invoiceFields.value.map((i) => ({
label: i.label,
value: i.slug,
@ -211,7 +213,8 @@ async function getFields() {
{ label: 'Date', value: 'ESTIMATE_DATE' },
{ label: 'Expiry Date', value: 'ESTIMATE_EXPIRY_DATE' },
{ label: 'Number', value: 'ESTIMATE_NUMBER' },
{ label: 'Ref Number', value: 'ESTIMATE_REF_NUMBER' },
{ label: 'PDF Link', value: 'PDF_LINK' },
{ label: 'Total Amount', value: 'TOTAL_AMOUNT' },
...estimateFields.value.map((i) => ({
label: i.label,
value: i.slug,
@ -228,6 +231,7 @@ async function getFields() {
{ label: 'Number', value: 'PAYMENT_NUMBER' },
{ label: 'Mode', value: 'PAYMENT_MODE' },
{ label: 'Amount', value: 'PAYMENT_AMOUNT' },
{ label: 'PDF Link', value: 'PDF_LINK' },
...paymentFields.value.map((i) => ({
label: i.label,
value: i.slug,

View File

@ -69,31 +69,29 @@
</div>
<div class="grid grid-cols-2 gap-8 mt-2">
<div v-if="selectedCustomer.billing" class="flex flex-col">
<label
<BaseLabel
class="
mb-1
text-sm
font-medium
text-left text-gray-400
uppercase
whitespace-nowrap
!mb-1
!text-left !text-gray-400
!uppercase
!whitespace-nowrap
"
>
{{ $t('general.bill_to') }}
</label>
</BaseLabel>
<div
v-if="selectedCustomer.billing"
class="flex flex-col flex-1 p-0 text-left"
>
<label
<BaseLabel
v-if="selectedCustomer.billing.name"
class="relative w-11/12 text-sm truncate"
class="!relative !w-11/12 !truncate"
>
{{ selectedCustomer.billing.name }}
</label>
</BaseLabel>
<label class="relative w-11/12 text-sm truncate">
<BaseLabel class="!relative !w-11/12 !truncate">
<span v-if="selectedCustomer.billing.city">
{{ selectedCustomer.billing.city }}
</span>
@ -108,42 +106,40 @@
<span v-if="selectedCustomer.billing.state">
{{ selectedCustomer.billing.state }}
</span>
</label>
<label
</BaseLabel>
<BaseLabel
v-if="selectedCustomer.billing.zip"
class="relative w-11/12 text-sm truncate"
class="!relative !w-11/12 !truncate"
>
{{ selectedCustomer.billing.zip }}
</label>
</BaseLabel>
</div>
</div>
<div v-if="selectedCustomer.shipping" class="flex flex-col">
<label
<BaseLabel
class="
mb-1
text-sm
font-medium
text-left text-gray-400
uppercase
whitespace-nowrap
!mb-1
!text-left !text-gray-400
!uppercase
!whitespace-nowrap
"
>
{{ $t('general.ship_to') }}
</label>
</BaseLabel>
<div
v-if="selectedCustomer.shipping"
class="flex flex-col flex-1 p-0 text-left"
>
<label
<BaseLabel
v-if="selectedCustomer.shipping.name"
class="relative w-11/12 text-sm truncate"
class="!relative !w-11/12 !truncate"
>
{{ selectedCustomer.shipping.name }}
</label>
</BaseLabel>
<label class="relative w-11/12 text-sm truncate">
<BaseLabel class="!relative !w-11/12 !truncate">
<span v-if="selectedCustomer.shipping.city">
{{ selectedCustomer.shipping.city }}
</span>
@ -158,13 +154,13 @@
<span v-if="selectedCustomer.shipping.state">
{{ selectedCustomer.shipping.state }}
</span>
</label>
<label
</BaseLabel>
<BaseLabel
v-if="selectedCustomer.shipping.zip"
class="relative w-11/12 text-sm truncate"
class="!relative !w-11/12 !text-sm !truncate"
>
{{ selectedCustomer.shipping.zip }}
</label>
</BaseLabel>
</div>
</div>
</div>
@ -211,7 +207,7 @@
/>
<div class="mt-1">
<label class="text-lg font-medium text-gray-900">
<label class="text-lg font-medium text-gray-900 dark:text-white">
{{ $t('customers.new_customer') }}
<span class="text-red-500"> * </span>
</label>
@ -335,9 +331,9 @@
v-if="customerStore.customers.length === 0"
class="flex justify-center p-5 text-gray-400"
>
<label class="text-base text-gray-500 cursor-pointer">
<BaseLabel class="!text-base !text-gray-500 !cursor-pointer">
{{ $t('customers.no_customers_found') }}
</label>
</BaseLabel>
</div>
</ul>
</div>
@ -362,19 +358,18 @@
>
<BaseIcon name="UserAddIcon" class="text-primary-400" />
<label
<BaseLabel
class="
m-0
ml-3
text-sm
leading-none
cursor-pointer
font-base
text-primary-400
!m-0
!ml-3
!leading-none
!cursor-pointer
!font-base
!text-primary-400
"
>
{{ $t('customers.add_new_customer') }}
</label>
</BaseLabel>
</button>
</PopoverPanel>
</div>

View File

@ -7,52 +7,108 @@
/>
</BaseContentPlaceholders>
<div v-else :class="computedContainerClass" class="relative flex flex-row">
<svg
v-if="showCalendarIcon && !hasIconSlot"
viewBox="0 0 20 20"
fill="currentColor"
class="
absolute
w-4
h-4
mx-2
my-2.5
text-sm
not-italic
font-black
text-gray-400
cursor-pointer
"
@click="onClickDp"
>
<path
fill-rule="evenodd"
d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z"
clip-rule="evenodd"
></path>
</svg>
<slot v-if="showCalendarIcon && hasIconSlot" name="icon" />
<FlatPickr
ref="dp"
<div v-else :class="computedContainerClass">
<date-picker
ref="vCalendar"
v-model="date"
v-bind="$attrs"
:disabled="disabled"
:config="config"
:class="[defaultInputClass, inputInvalidClass, inputDisabledClass]"
/>
:mode="mode"
:is24hr="time24hr"
class="w-full"
color="indigo"
:input-debounce="500"
:update-on-input="false"
:is-range="false"
trim-weeks
:is-required="isRequired"
:popover="{
visibility: disabled ? 'hidden' : 'focus',
showDelay: 0,
hideDelay: 1,
}"
:attributes="attrs"
:model-config="config"
:masks="masks"
:locale="global.locale"
>
<template
#default="{ inputValue, inputEvents, togglePopover, hidePopover }"
>
<!-- calendar icon -->
<svg
v-if="showCalendarIcon && !hasIconSlot"
viewBox="0 0 20 20"
fill="currentColor"
class="
absolute
w-4
h-4
mx-2
my-2.5
text-sm
not-italic
font-black
text-gray-400
cursor-pointer
"
@click="togglePopover()"
>
<path
fill-rule="evenodd"
d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z"
clip-rule="evenodd"
></path>
</svg>
<slot v-if="showCalendarIcon && hasIconSlot" name="icon" />
<input
:value="inputValue"
:class="[defaultInputClass, inputInvalidClass, inputDisabledClass]"
readonly
v-on="inputEvents"
@blur="hidePopover()"
/>
</template>
<template v-if="showExtraOptions" #footer>
<div
class="bg-gray-100 grid grid-cols-3 gap-2 p-2 border-t rounded-b-lg"
>
<button type="button" class="extra-button" @click="moveToDate(sourceDate)">
{{ global.t('date_picker.same_day') }}
</button>
<button type="button" class="extra-button" @click="withInDays(7)">
{{ global.t('date_picker.within_7_days') }}
</button>
<button type="button" class="extra-button" @click="withInDays(15)">
{{ global.t('date_picker.within_15_days') }}
</button>
<button type="button" class="extra-button" @click="withInDays(30)">
{{ global.t('date_picker.within_30_days') }}
</button>
<button type="button" class="extra-button" @click="withInDays(45)">
{{ global.t('date_picker.within_45_days') }}
</button>
<button type="button" class="extra-button" @click="withInDays(60)">
{{ global.t('date_picker.within_60_days') }}
</button>
</div>
</template>
</date-picker>
</div>
</template>
<script type="text/babel" setup>
import FlatPickr from 'vue-flatpickr-component'
import 'flatpickr/dist/flatpickr.css'
import { Calendar, DatePicker } from 'v-calendar'
import 'v-calendar/dist/style.css'
import { computed, reactive, watch, ref, useSlots } from 'vue'
import { useCompanyStore } from '@/scripts/admin/stores/company'
const dp = ref(null)
import moment from 'moment'
const props = defineProps({
modelValue: {
@ -90,36 +146,31 @@ const props = defineProps({
defaultInputClass: {
type: String,
default:
'font-base pl-8 py-2 outline-none focus:ring-primary-400 focus:outline-none focus:border-primary-400 block w-full sm:text-sm border-gray-200 rounded-md text-black',
'border-2 font-base pl-8 py-2 outline-none focus:ring-primary-400 focus:outline-none focus:border-primary-400 block w-full sm:text-sm border-gray-200 rounded-md text-black',
},
time24hr: {
type: Boolean,
default: false,
},
isRequired: {
type: Boolean,
default: false,
},
showExtraOptions: {
type: Boolean,
default: false,
},
sourceDate: {
type: [String, Date],
default: () => new Date(),
}
})
const emit = defineEmits(['update:modelValue'])
const slots = useSlots()
const companyStore = useCompanyStore()
let config = reactive({
altInput: true,
enableTime: props.enableTime,
time_24hr: props.time24hr,
})
const date = computed({
get: () => props.modelValue,
set: (value) => {
emit('update:modelValue', value)
},
})
const carbonFormat = computed(() => {
return companyStore.selectedCompanySettings?.carbon_date_format
})
const { global } = window.i18n
const vCalendar = ref(null)
const hasIconSlot = computed(() => {
return !!slots.icon
@ -135,7 +186,6 @@ const inputInvalidClass = computed(() => {
if (props.invalid) {
return 'border-red-400 ring-red-400 focus:ring-red-400 focus:border-red-400'
}
return ''
})
@ -143,35 +193,97 @@ const inputDisabledClass = computed(() => {
if (props.disabled) {
return 'border border-solid rounded-md outline-none input-field box-border-2 base-date-picker-input placeholder-gray-400 bg-gray-200 text-gray-600 border-gray-200'
}
return ''
})
function onClickDp(params) {
dp.value.fp.open()
// to convert YYYY-MM-DD | YYYY-MM-DD HH:mm format
function convertYMDFormat(date) {
let format = props.enableTime ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD'
return date ? moment(date).format(format) : date
}
watch(
() => props.enableTime,
(val) => {
if (props.enableTime) {
config.enableTime = props.enableTime
}
const date = computed({
get: () => props.modelValue,
set: (value) => {
emit('update:modelValue', value)
},
{ immediate: true }
)
})
const mode = computed(() => {
return props.enableTime ? 'dateTime' : 'date'
})
const config = reactive({
type: 'string',
mask: 'YYYY-MM-DD', // Uses 'iso' if missing
//timeAdjust: '00:00:00',
})
const masks = reactive({
input: null,
inputDateTime: null,
inputDateTime24hr: null,
})
const attrs = reactive([
{
dates: new Date(),
highlight: {
fillMode: 'outline',
},
/* popover: {
label: 'Today Date',
visibility: 'hover',
}, */
},
])
const carbonFormat = computed(() => {
return companyStore.selectedCompanySettings?.moment_date_format
})
watch(
() => carbonFormat,
() => {
if (!props.enableTime) {
config.altFormat = carbonFormat.value ? carbonFormat.value : 'd M Y'
masks.input = carbonFormat.value ? carbonFormat.value : 'DD MMM YYYY'
config.mask = 'YYYY-MM-DD'
} else {
config.altFormat = carbonFormat.value
? `${carbonFormat.value} H:i `
: 'd M Y H:i'
let timeFormat = 'HH:mm'
if (props.time24hr) {
masks.inputDateTime24hr = carbonFormat.value
? `${carbonFormat.value} ${timeFormat}`
: `DD MMM YYYY ${timeFormat}`
} else {
masks.inputDateTime = carbonFormat.value
? `${carbonFormat.value} ${timeFormat}`
: `DD MMM YYYY ${timeFormat}`
}
config.mask = `YYYY-MM-DD ${timeFormat}`
}
},
{ immediate: true }
)
async function moveToDate(_date) {
const calendar = vCalendar.value
_date = _date ? _date : convertYMDFormat(new Date())
date.value = _date
// await calendar.move(_date)
calendar.hidePopover()
}
async function withInDays(noOfDays) {
if (!noOfDays) return false
let newDate = moment(props.sourceDate).add(noOfDays, 'days').toDate()
newDate = convertYMDFormat(newDate)
moveToDate(newDate)
}
</script>
<style scoped>
.extra-button {
@apply bg-primary-500 text-white text-sm font-semibold px-2 py-1 rounded hover:bg-primary-700;
}
</style>

View File

@ -4,10 +4,10 @@
<slot></slot>
</div>
<div class="mt-2">
<label class="font-medium">{{ title }}</label>
<BaseLabel >{{ title }}</BaseLabel>
</div>
<div class="mt-2">
<label class="text-gray-500">
<label class="text-gray-500 dark:text-gray-400">
{{ description }}
</label>
</div>

View File

@ -20,6 +20,7 @@
hover:text-gray-700
top-2.5
right-3.5
dark:text-gray-300
"
@click="$emit('clear')"
>

View File

@ -3,18 +3,15 @@
<BaseContentPlaceholders v-if="contentLoading">
<BaseContentPlaceholdersText :lines="1" :class="contentLoadClass" />
</BaseContentPlaceholders>
<label
<BaseLabel
v-else-if="label"
:class="labelClasses"
class="
flex
text-sm
not-italic
items-center
font-medium
text-gray-800
whitespace-nowrap
justify-between
!flex
!items-center
!text-gray-800
!whitespace-nowrap
!justify-between
"
>
<div>
@ -28,10 +25,10 @@
name="InformationCircleIcon"
class="h-4 text-gray-400 cursor-pointer hover:text-gray-600"
/>
</label>
</BaseLabel>
<div :class="inputContainerClasses">
<slot></slot>
<span v-if="helpText" class="text-gray-500 text-xs mt-1 font-light">
<span v-if="helpText" class="text-gray-500 text-xs mt-1 font-light dark:text-gray-400">
{{ helpText }}
</span>
<span v-if="error" class="block mt-0.5 text-sm text-red-500">

View File

@ -1,5 +1,5 @@
<template>
<label class="text-sm not-italic font-medium leading-5 text-primary-800">
<label class="text-sm not-italic font-medium leading-5 text-primary-800 dark:!text-gray-300">
<slot />
</label>
</template>

View File

@ -1,6 +1,10 @@
<template>
<div>
<TabGroup :default-index="defaultIndex" @change="onChange">
<TabGroup
:selected-index="selectedIndex"
:default-index="defaultIndex"
@change="onChange"
>
<TabList
:class="[
'flex border-b border-grey-light',
@ -54,6 +58,10 @@ const props = defineProps({
type: Number,
default: 0,
},
selectedIndex: {
type: Number,
default: 0,
},
filter: {
type: String,
default: null,
@ -67,6 +75,6 @@ const slots = useSlots()
const tabs = computed(() => slots.default().map((tab) => tab.props))
function onChange(d) {
emit('change', tabs.value[d])
emit('change', tabs.value[d], d)
}
</script>

View File

@ -7,12 +7,12 @@ export function usePopper(options) {
let popper = ref(null)
onMounted(() => {
watchEffect(onInvalidate => {
watchEffect((onInvalidate) => {
if (!container.value) return
if (!activator.value) return
let containerEl = container.value.el || container.value
let activatorEl = activator.value.el || activator.value
let activatorEl = activator.value.$el || activator.value
if (!(activatorEl instanceof HTMLElement)) return
if (!(containerEl instanceof HTMLElement)) return

View File

@ -4,7 +4,7 @@
"customers": "العملاء",
"items": "بضائع/خدمات",
"invoices": "الفواتير",
"recurring-invoices": "الفواتير المتكررة",
"recurring-invoices": "Recurring Invoices",
"expenses": "النفقات",
"estimates": "التقديرات",
"payments": "الدفوعات",
@ -12,7 +12,7 @@
"settings": "الإعدادات",
"logout": "تسجيل الخروج",
"users": "المستخدمون",
"modules": "الإضافات"
"modules": "Modules"
},
"general": {
"add_company": "أضف شركة",
@ -29,9 +29,9 @@
"to_date": "إلى تاريخ",
"from": "من",
"to": "إلى",
"ok": "حسناً",
"yes": "نعم",
"no": "لا",
"ok": "Ok",
"yes": "Yes",
"no": "No",
"sort_by": "ترتيب حسب",
"ascending": "تصاعدي",
"descending": "تنازلي",
@ -39,7 +39,7 @@
"body": "الجسم",
"message": "رسالة",
"send": "إرسال",
"preview": "معاينة",
"preview": "Preview",
"go_back": "إلى الخلف",
"back_to_login": "العودة إلى تسجيل الدخول؟",
"home": "الرئيسية",
@ -65,7 +65,7 @@
"sent": "ارسلت",
"all": "الكل",
"select_all": "تحديد الكل",
"select_template": "تحديد القالب",
"select_template": "Select Template",
"choose_file": "اضغط هنا لاختيار ملف",
"choose_template": "اختيار القالب",
"choose": "اختر",
@ -93,14 +93,14 @@
"no_note_found": "لم يتم العثور على الملاحظة",
"insert_note": "أدخل ملاحظة",
"copied_pdf_url_clipboard": "تم نسخ رابط PDF إلى الحافظة!",
"copied_url_clipboard": "تم نسخ الرابط إلى الحافظة!",
"docs": "المستندات",
"do_you_wish_to_continue": "هل ترغب في المتابعة؟",
"note": "ملاحظة",
"pay_invoice": "سدد الفاتورة",
"login_successfully": "تم تسجيل الدخول بنجاح!",
"logged_out_successfully": "تم تسجيل الخروج",
"mark_as_default": "تحديد كافتراضي"
"copied_url_clipboard": "Copied url to clipboard!",
"docs": "Docs",
"do_you_wish_to_continue": "Do you wish to continue?",
"note": "Note",
"pay_invoice": "Pay Invoice",
"login_successfully": "Logged in successfully!",
"logged_out_successfully": "Logged out successfully",
"mark_as_default": "Mark as default"
},
"dashboard": {
"select_year": "اختر السنة",
@ -109,7 +109,7 @@
"customers": "العملاء",
"invoices": "الفواتير",
"estimates": "التقديرات",
"payments": "المدفوعات"
"payments": "Payments"
},
"chart_info": {
"total_sales": "المبيعات",
@ -151,27 +151,27 @@
"no_results_found": "لم يتم العثور على نتائج"
},
"company_switcher": {
"label": "تبديل الشركة",
"no_results_found": "لا توجد نتائج",
"add_new_company": "إضافة شركة جديدة",
"new_company": "شركة جديدة",
"created_message": "تم إنشاء الشركة بنجاح"
"label": "SWITCH COMPANY",
"no_results_found": "No Results Found",
"add_new_company": "Add new company",
"new_company": "New company",
"created_message": "Company created successfully"
},
"dateRange": {
"today": "اليوم",
"this_week": "هذا الاسبوع",
"this_month": "هذا الشهر",
"this_quarter": "هذا الربع",
"this_year": "هذه السنة",
"previous_week": "الأسبوع السابق",
"previous_month": "الشهر الماضي",
"previous_quarter": "الربع السابق",
"previous_year": "السنة الماضية",
"custom": "مخصص"
"today": "Today",
"this_week": "This Week",
"this_month": "This Month",
"this_quarter": "This Quarter",
"this_year": "This Year",
"previous_week": "Previous Week",
"previous_month": "Previous Month",
"previous_quarter": "Previous Quarter",
"previous_year": "Previous Year",
"custom": "Custom"
},
"customers": {
"title": "العملاء",
"prefix": "البادئة",
"prefix": "Prefix",
"add_customer": "إضافة عميل",
"contacts_list": "قائمة العملاء",
"name": "الاسم",
@ -186,9 +186,9 @@
"phone": "الهاتف",
"website": "موقع الإنترنت",
"overview": "استعراض",
"invoice_prefix": "بادئة الفاتورة",
"estimate_prefix": "بادئة رقم التقدير",
"payment_prefix": "بادئة رقم الدفعة",
"invoice_prefix": "Invoice Prefix",
"estimate_prefix": "Estimate Prefix",
"payment_prefix": "Payment Prefix",
"enable_portal": "تفعيل البوابة",
"country": "الدولة",
"state": "الولاية/المنطقة",
@ -197,7 +197,7 @@
"added_on": "أضيف في",
"action": "إجراء",
"password": "كلمة المرور",
"confirm_password": "تأكيد كلمة المرور",
"confirm_password": "Confirm Password",
"street_number": "رقم الشارع",
"primary_currency": "العملة الرئيسية",
"description": "الوصف",
@ -208,10 +208,10 @@
"new_customer": "عميل جديد",
"edit_customer": "تعديل عميل",
"basic_info": "معلوات أساسية",
"portal_access": "الوصول إلى بوابة العملاء",
"portal_access_text": "هل تريد السماح لهذا العميل بتسجيل الدخول إلى بوابة العملاء؟",
"portal_access_url": "رابط بوابة العملاء",
"portal_access_url_help": "يرجى نسخ وإعادة إرسال عنوان URL أعلاه إلى الزبون لتوفير الوصول.",
"portal_access": "Portal Access",
"portal_access_text": "Would you like to allow this customer to login to the Customer Portal?",
"portal_access_url": "Customer Portal Login URL",
"portal_access_url_help": "Please copy & forward the above given URL to your customer for providing access.",
"billing_address": "عنوان الفوترة",
"shipping_address": "عنوان الشحن",
"copy_billing_address": "نسخ من عنوان الفوترة",
@ -231,9 +231,9 @@
"confirm_delete": "لن تتمكن من استرداد هذا العميل وجميع الفواتير والتقديرات والمدفوعات ذات الصلة. | لن تتمكن من استرداد هؤلاء العملاء وجميع الفواتير والتقديرات والمدفوعات ذات الصلة.",
"created_message": "تم إنشاء العملاء بنجاح",
"updated_message": "تم تحديث العملاء بنجاح",
"address_updated_message": "تم تحديث العنوان بنجاح",
"address_updated_message": "Address Information Updated succesfully",
"deleted_message": "تم حذف العملاء بنجاح | تم حذف العميل بنجاح",
"edit_currency_not_allowed": "لا يمكن تغيير العملة بمجرد إنشاء معاملة."
"edit_currency_not_allowed": "Cannot change currency once transactions created."
},
"items": {
"title": "الأصناف",
@ -265,8 +265,8 @@
},
"estimates": {
"title": "التقديرات",
"accept_estimate": "قبول التقدير",
"reject_estimate": "رفض التقدير",
"accept_estimate": "Accept Estimate",
"reject_estimate": "Reject Estimate",
"estimate": "تقدير | تقديرات",
"estimates_list": "قائمة التقديرات",
"days": "{days} أيام",
@ -318,10 +318,10 @@
},
"accepted": "مقبول",
"rejected": "مرفوض",
"expired": "انتهت مدة الصلاحية",
"expired": "Expired",
"sent": "مرسل",
"draft": "مسودة",
"viewed": "تمت المشاهدة",
"viewed": "Viewed",
"declined": "مرفوض",
"new_estimate": "تقدير جديد",
"add_new_estimate": "إضافة تقدير جديد",
@ -355,14 +355,14 @@
"select_an_item": "اكتب أو اختر الصنف",
"type_item_description": "اكتب وصف الصنف (اختياري)"
},
"mark_as_default_estimate_template_description": "في حالة التعفيل، سيتم اختيار القالب المحدد تلقائياً للتقديرات الجديدة."
"mark_as_default_estimate_template_description": "If enabled, the selected template will be automatically selected for new estimates."
},
"invoices": {
"title": "الفواتير",
"download": "تحميل",
"pay_invoice": "سدد الفاتورة",
"download": "Download",
"pay_invoice": "Pay Invoice",
"invoices_list": "قائمة الفواتير",
"invoice_information": "معلومات الفاتورة",
"invoice_information": "Invoice Information",
"days": "{days} أيام",
"months": "{months} أشهر",
"years": "{years} سنوات",
@ -397,13 +397,13 @@
"send_invoice": "إرسال الفاتورة",
"resend_invoice": "إعادة إرسال الفاتورة",
"invoice_template": "قالب الفاتورة",
"conversion_message": "تم استنساخ الفاتورة بنجاح",
"conversion_message": "Invoice cloned successful",
"template": "قالب",
"mark_as_sent": "تحديد كمرسل",
"confirm_send_invoice": "سيتم إرسال هذه الفاتورة بالبريد الألكتروني إلى العميل",
"invoice_mark_as_sent": "سيتم تحديد هذه الفاتورة كمرسلة",
"confirm_mark_as_accepted": "سيتم تحديد هذه الفاتورة كمقبولة",
"confirm_mark_as_rejected": "سيتم تحديد هذه الفاتورة كمرفوضة",
"confirm_mark_as_accepted": "This invoice will be marked as Accepted",
"confirm_mark_as_rejected": "This invoice will be marked as Rejected",
"confirm_send": "سيتم إرسال هذه الفاتورة بالبريد الألكتروني إلى العميل",
"invoice_date": "تاريخ الفاتورة",
"record_payment": "تسجيل مدفوعات",
@ -415,13 +415,13 @@
"update_invoice": "تحديث الفاتورة",
"add_new_tax": "إضافة ضريبة جديدة",
"no_invoices": "لا يوجد فواتير حتى الآن!",
"mark_as_rejected": "تحديد كمرفوض",
"mark_as_accepted": "تحديد كمقبول",
"mark_as_rejected": "Mark as rejected",
"mark_as_accepted": "Mark as accepted",
"list_of_invoices": "قائمة الفواتير .",
"select_invoice": "اختر الفاتورة",
"no_matching_invoices": "لا يوجد فواتير مطابقة!",
"mark_as_sent_successfully": "تم تحديد الفاتورة كمرسلة بنجاح",
"invoice_sent_successfully": "تم إرسال الفاتورة بنجاح",
"invoice_sent_successfully": "Invoice sent successfully",
"cloned_successfully": "تم استنساخ الفاتورة بنجاح",
"clone_invoice": "استنساخ الفاتورة",
"confirm_clone": "سيتم استنساخ هذه الفاتورة في فاتورة جديدة",
@ -447,14 +447,14 @@
"marked_as_sent_message": "تم إرسال الفاتورة بنجاح",
"something_went_wrong": "خطأ غير معروف!",
"invalid_due_amount_message": "المبلغ النهائي للفاتورة لا يمكن أن يكون أقل من المبلغ المطلوب لها. رجاءاً حدث الفاتورة أو قم بحذف المدفوعات المرتبطة بها للاستمرار.",
"mark_as_default_invoice_template_description": "في حالة التفعيل، سيتم اختيار القالب المحدد تلقائياً للفواتير الجديدة."
"mark_as_default_invoice_template_description": "If enabled, the selected template will be automatically selected for new invoices."
},
"recurring_invoices": {
"title": "الفواتير المتكررة",
"invoices_list": "الفواتير المتكررة",
"days": "{days} أيام",
"months": "{months} أشهر",
"years": "{years} سنوات",
"title": "Recurring Invoices",
"invoices_list": "Recurring Invoices List",
"days": "{days} Days",
"months": "{months} Month",
"years": "{years} Year",
"all": "All",
"paid": "Paid",
"unpaid": "Unpaid",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "تقدير",
"pdf_estimate_number": "رقم تقدير",
"pdf_estimate_date": "تاريخ التقدير",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "تاريخ انتهاء الصلاحية",
"pdf_invoice_label": "الفاتورة",
"pdf_invoice_number": "رقم الفاتورة",
"pdf_invoice_date": "تاريخ الفاتورة",

View File

@ -112,7 +112,7 @@
"payments": "Platby"
},
"chart_info": {
"total_sales": "Prodeje",
"total_sales": "Slevy",
"total_receipts": "Doklady",
"total_expense": "Výdaje",
"net_income": "Čistý příjem",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Odhad",
"pdf_estimate_number": "Číslo odhadu",
"pdf_estimate_date": "Datum odhadu",
"pdf_estimate_expire_date": "Datum expirace",
"pdf_estimate_expire_date": "Doba platnosti",
"pdf_invoice_label": "Faktura",
"pdf_invoice_number": "Číslo faktury",
"pdf_invoice_date": "Datum fakturace",
@ -1495,7 +1495,7 @@
"pdf_quantity_label": "Množství",
"pdf_price_label": "Cena",
"pdf_discount_label": "Sleva",
"pdf_amount_label": "Částka",
"pdf_amount_label": "Množství",
"pdf_subtotal": "Mezisoučet",
"pdf_total": "Celkem",
"pdf_payment_label": "Platba",

View File

@ -688,7 +688,7 @@
"other_modules": "Weitere Module",
"view_all": "Alle Anzeigen",
"no_reviews_found": "Für dieses Modul gibt es noch keine Bewertungen!",
"module_not_purchased": "Modul noch nicht erworben",
"module_not_purchased": "Module Not Purchased",
"module_not_found": "Modul nicht gefunden",
"version_not_supported": "This module version doesn't support the current version of Crater",
"last_updated": "Zuletzt aktualisiert am",
@ -1113,7 +1113,7 @@
"default_currency_error": "Diese Währung wird bereits in einem der aktiven Anbieter verwendet",
"exchange_help_text": "Wechselkurs eingeben um von {currency} nach {baseCurrency} zu konvertieren",
"currency_freak": "CurrencyFreaks",
"currency_layer": "Währungsebene",
"currency_layer": "Currency Layer",
"open_exchange_rate": "Open Exchange Rate",
"currency_converter": "Währungsumrechner",
"server": "Server",
@ -1150,8 +1150,8 @@
"payment_mode_added": "Zahlungsart hinzugefügt",
"payment_mode_updated": "Zahlungsart aktualisiert",
"payment_mode_confirm_delete": "Sie werden diese Zahlungsart nicht wiederherstellen können",
"payments_attached": "Diese Zahlungsmethode ist bereits mit Zahlungen verknüpft. Bitte löschen Sie die angehängten Zahlungen, um mit der Löschung fortzufahren.",
"expenses_attached": "Diese Zahlungsmethode ist bereits mit Ausgaben verknüpft. Bitte löschen Sie die angehängten Ausgaben, um mit der Löschung fortzufahren.",
"payments_attached": "This payment method is already attached to payments. Please delete the attached payments to proceed with deletion.",
"expenses_attached": "This payment method is already attached to expenses. Please delete the attached expenses to proceed with deletion.",
"deleted_message": "Zahlungsart erfolgreich gelöscht"
},
"expense_category": {
@ -1179,7 +1179,7 @@
"discount_per_item": "Rabatt pro Artikel ",
"discount_setting_description": "Aktivieren Sie diese Option, wenn Sie einzelnen Rechnungspositionen einen Rabatt hinzufügen möchten. Standardmäßig wird der Rabatt direkt zur Rechnung hinzugefügt.",
"expire_public_links": "Öffentliche Links automatisch ablaufen lassen",
"expire_setting_description": "Geben Sie an, ob Sie alle von der Anwendung gesendeten Links zur Ansicht von Rechnungen, Kostenvoranschlägen und Zahlungen usw. nach einer bestimmten Zeit ablaufen lassen möchten.",
"expire_setting_description": "Specify whether you would like to expire all the links sent by application to view invoices, estimates & payments, etc after a specified duration.",
"save": "Speichern",
"preference": "Präferenz | Präferenzen",
"general_settings": "Standardeinstellungen für das System.",
@ -1272,14 +1272,14 @@
"do_spaces_secret": "Do Spaces Secret",
"do_spaces_region": "Do Spaced Region",
"do_spaces_bucket": "Do Spaces Bucket",
"do_spaces_endpoint": "Do Spaces Endpunkt",
"do_spaces_endpoint": "Do Spaces Endpoint",
"do_spaces_root": "Do Spaced Root",
"dropbox_type": "Dropbox Typ",
"dropbox_token": "Dropbox Token",
"dropbox_key": "Dropbox Schlüssel",
"dropbox_secret": "Dropbox Secret",
"dropbox_app": "Dropbox App",
"dropbox_root": "Dropbox Root Verzeichnis",
"dropbox_root": "Dropbox Root",
"default_driver": "Standard-Treiber",
"is_default": "Standard",
"set_default_disk": "Als Standard festlegen",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Angebot",
"pdf_estimate_number": "Angebotsnummer",
"pdf_estimate_date": "Angebotsdatum",
"pdf_estimate_expire_date": "Zahlungsziel",
"pdf_estimate_expire_date": "Gültig bis",
"pdf_invoice_label": "Rechnung",
"pdf_invoice_number": "Rechnungsnummer",
"pdf_invoice_date": "Rechnungsdatum",

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Εκτίμηση",
"pdf_estimate_number": "Εκτίμηση Αριθμού",
"pdf_estimate_date": "Εκτιμώμενη ημ. επισκευής",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Ημερομηνία λήξης",
"pdf_invoice_label": "Τιμολόγιο",
"pdf_invoice_number": "Αριθμός τιμολογίου",
"pdf_invoice_date": "Ημ/νία Τιμολόγησης",

View File

@ -863,6 +863,8 @@
"company_info": {
"company_info": "Company info",
"company_name": "Company Name",
"company_slug": "Company Slug",
"company_slug_help_text": "A unique URL friendly name for your company (It will appear on Customer Portal URL)",
"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",
@ -1324,6 +1326,8 @@
"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_slug": "Company Slug",
"company_slug_help_text": "A unique URL friendly name for your company (It will appear on Customer Portal URL)",
"company_logo": "Company Logo",
"logo_preview": "Logo Preview",
"preferences": "Company Preferences",
@ -1454,7 +1458,8 @@
"at_least_one_ability": "Please select atleast one Permission.",
"valid_driver_key": "Please enter a valid {driver} key.",
"valid_exchange_rate": "Please enter a valid exchange rate.",
"company_name_not_same": "Company name must match with given name."
"company_name_not_same": "Company name must match with given name.",
"invalid_slug": "Invalid Slug"
},
"errors": {
"starter_plan": "This feature is available on Starter plan and onwards!",
@ -1522,5 +1527,13 @@
"pdf_bill_to": "Bill to,",
"pdf_ship_to": "Ship to,",
"pdf_received_from": "Received from:",
"pdf_tax_label": "Tax"
"pdf_tax_label": "Tax",
"date_picker": {
"same_day": "Same Day",
"within_7_days": "Within 7 Days",
"within_15_days": "Within 15 Days",
"within_30_days": "Within 30 Days",
"within_45_days": "Within 45 Days",
"within_60_days": "Within 60 Days"
}
}

View File

@ -1,6 +1,6 @@
{
"navigation": {
"dashboard": "Panel de Control",
"dashboard": "Tablero",
"customers": "Clientes",
"items": "Artículos",
"invoices": "Facturas",
@ -9,7 +9,7 @@
"estimates": "Presupuestos",
"payments": "Pagos",
"reports": "Informes",
"settings": "Configuración",
"settings": "Ajustes",
"logout": "Cerrar sesión",
"users": "Usuarios",
"modules": "Módulos"
@ -47,7 +47,7 @@
"delete": "Eliminar",
"edit": "Editar",
"view": "Ver",
"add_new_item": "Agregar Nuevo Artículo",
"add_new_item": "Agregar ítem nuevo",
"clear_all": "Limpiar todo",
"showing": "Mostrar",
"of": "de",
@ -87,7 +87,7 @@
"select_city": "Seleccionar ciudad",
"street_1": "Calle 1",
"street_2": "Calle 2",
"action_failed": "Acción Fallida",
"action_failed": "Accion Fallida",
"retry": "Procesar de nuevo",
"choose_note": "Elegir nota",
"no_note_found": "No se encontró ninguna nota",
@ -98,7 +98,7 @@
"do_you_wish_to_continue": "¿Deseas continuar?",
"note": "Nota",
"pay_invoice": "Pagar factura",
"login_successfully": "¡Sesión inciada con éxito!",
"login_successfully": "Logeado Satisfactoriamente!",
"logged_out_successfully": "Logeado Satisfactoriamente",
"mark_as_default": "Marcar como predeterminado"
},
@ -113,7 +113,7 @@
},
"chart_info": {
"total_sales": "Ventas",
"total_receipts": "Recibos",
"total_receipts": "Ingresos",
"total_expense": "Gastos",
"net_income": "Ingresos netos",
"year": "Seleccione año"
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Presupuestar",
"pdf_estimate_number": "Número de Presupuesto",
"pdf_estimate_date": "Fecha presupuesto",
"pdf_estimate_expire_date": "Fecha de vencimiento",
"pdf_estimate_expire_date": "Fecha de caducidad",
"pdf_invoice_label": "Factura",
"pdf_invoice_number": "Numero de factura",
"pdf_invoice_date": "Fecha de la factura",

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Estimate",
"pdf_estimate_number": "Estimate Number",
"pdf_estimate_date": "Estimate Date",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Expiry date",
"pdf_invoice_label": "Invoice",
"pdf_invoice_number": "Invoice Number",
"pdf_invoice_date": "Invoice Date",

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Tarjous",
"pdf_estimate_number": "Tarjousnumero",
"pdf_estimate_date": "Tarjouksen päiväys",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Voimassaolo päivä",
"pdf_invoice_label": "Lasku",
"pdf_invoice_number": "Laskunumero",
"pdf_invoice_date": "Laskun päiväys",

View File

@ -310,7 +310,7 @@
"confirm_mark_as_sent": "Ce devis sera marqué comme envoyé",
"confirm_mark_as_accepted": "Ce devis sera marqué comme accepté",
"confirm_mark_as_rejected": "Ce devis sera marqué comme rejeté",
"no_matching_estimates": "Aucun devis correspondant !",
"no_matching_estimates": "Aucune estimation correspondante !",
"mark_as_sent_successfully": "Devis marqué comme envoyé",
"send_estimate_successfully": "Devis envoyé",
"errors": {
@ -355,7 +355,7 @@
"select_an_item": "Sélectionnez un article",
"type_item_description": "Taper la description de l'article (facultatif)"
},
"mark_as_default_estimate_template_description": "Si activé, le modèle sélectionné sera automatiquement utilisé pour les nouvelles estimations."
"mark_as_default_estimate_template_description": "If enabled, the selected template will be automatically selected for new estimates."
},
"invoices": {
"title": "Factures",
@ -447,7 +447,7 @@
"marked_as_sent_message": "Facture supprimée | Factures supprimées",
"something_went_wrong": "quelque chose a mal tourné",
"invalid_due_amount_message": "Le paiement entré est supérieur au montant total dû pour cette facture. Veuillez vérifier et réessayer.",
"mark_as_default_invoice_template_description": "Si activé, le modèle sélectionné sera automatiquement utilisé pour les nouvelles factures."
"mark_as_default_invoice_template_description": "If enabled, the selected template will be automatically selected for new invoices."
},
"recurring_invoices": {
"title": "Factures récurrentes",
@ -526,7 +526,7 @@
"cloned_successfully": "Facture récurrente clonée",
"clone_invoice": "Dupliquer",
"confirm_clone": "Cette facture récurrente sera clonée dans une nouvelle facture récurrente",
"add_customer_email": "Veuillez ajouter une adresse e-mail pour ce client afin d'envoyer les factures automatiquement.",
"add_customer_email": "Please add an email address for this customer to send invoices automatically.",
"item": {
"title": "Nom",
"description": "Description",
@ -844,9 +844,9 @@
"secret": "Secret",
"mailgun_secret": "Secret Mailgun",
"mailgun_domain": "Domaine",
"mailgun_endpoint": "Endpoint de Mailgun",
"ses_secret": "Clé secrète SES",
"ses_key": "Clé SES",
"mailgun_endpoint": "Mailgun Endpoint",
"ses_secret": "SES Secret",
"ses_key": "SES Key",
"password": "Mot de passe",
"username": "Nom d'utilisateur",
"mail_config": "Envoi d'emails",
@ -1112,10 +1112,10 @@
"error": "Vous ne pouvez pas supprimer le fournisseur actif",
"default_currency_error": "Cette devise est déjà affectée à un fournisseur",
"exchange_help_text": "Veuillez entrer le taux de change pour convertir {currency} en {baseCurrency}",
"currency_freak": "Currency Freaks",
"currency_freak": "Currency Freak",
"currency_layer": "Currency Layer",
"open_exchange_rate": "Ouvrir le taux de change",
"currency_converter": "Convertisseur de devises",
"open_exchange_rate": "Open Exchange Rate",
"currency_converter": "Currency Converter",
"server": "Serveur",
"url": "URL",
"active": "Actif",
@ -1150,8 +1150,8 @@
"payment_mode_added": "Mode de paiement ajouté",
"payment_mode_updated": "Mode de paiement mis à jour",
"payment_mode_confirm_delete": "Vous ne pourrez pas récupérer ce mode de paiement",
"payments_attached": "Ce moyen de paiement est déjà utilisé par des paiements. Merci de supprimer les paiements associés avant de procéder à la suppression.",
"expenses_attached": "Ce moyen de paiement est déjà utilisé par des dépenses. Merci de supprimer les dépenses associés avant de procéder à la suppression.",
"payments_attached": "This payment method is already attached to payments. Please delete the attached payments to proceed with deletion.",
"expenses_attached": "This payment method is already attached to expenses. Please delete the attached expenses to proceed with deletion.",
"deleted_message": "Mode de paiement supprimé"
},
"expense_category": {
@ -1262,8 +1262,8 @@
"media_driver": "Stockage multimédia",
"media_root": "Répertoire média",
"aws_driver": "AWS",
"aws_key": "Clé AWS",
"aws_secret": "Clé secrète AWS",
"aws_key": "AWS Key",
"aws_secret": "AWS Secret",
"aws_region": "Région AWS",
"aws_bucket": "Bucket",
"aws_root": "Répertoire",
@ -1491,7 +1491,7 @@
"pdf_invoice_date": "Date",
"pdf_invoice_due_date": "Date déchéance",
"pdf_notes": "Notes de bas de page",
"pdf_items_label": "Désignation",
"pdf_items_label": "Articles",
"pdf_quantity_label": "Quantité",
"pdf_price_label": "Prix",
"pdf_discount_label": "Remise",

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Estimate",
"pdf_estimate_number": "Estimate Number",
"pdf_estimate_date": "Estimate Date",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Expiry date",
"pdf_invoice_label": "Invoice",
"pdf_invoice_number": "Invoice Number",
"pdf_invoice_date": "Invoice Date",

View File

@ -4,7 +4,7 @@
"customers": "Klijenti",
"items": "Stavke",
"invoices": "Fakture",
"recurring-invoices": "Ponavljajuće fakture\n",
"recurring-invoices": "Recurring Invoices",
"expenses": "Rashodi",
"estimates": "Ponude",
"payments": "Uplate",
@ -12,7 +12,7 @@
"settings": "Postavke",
"logout": "Odjava",
"users": "Korisnici",
"modules": "Moduli"
"modules": "Modules"
},
"general": {
"add_company": "Dodaj tvrtku",
@ -30,8 +30,8 @@
"from": "Pošiljatelj",
"to": "Primatelj",
"ok": "Ok",
"yes": "Da",
"no": "Ne",
"yes": "Yes",
"no": "No",
"sort_by": "Posloži Po",
"ascending": "Rastuće",
"descending": "Padajuće",
@ -39,7 +39,7 @@
"body": "Tijelo",
"message": "Poruka",
"send": "Pošalji",
"preview": "Pregled",
"preview": "Preview",
"go_back": "Natrag",
"back_to_login": "Natrag na prijavu?",
"home": "Početna",
@ -65,7 +65,7 @@
"sent": "Poslano",
"all": "Sve",
"select_all": "Izaberi sve",
"select_template": "Odaberite predložak",
"select_template": "Select Template",
"choose_file": "Klikni ovdje da izabereš fajl",
"choose_template": "Izaberi predložak",
"choose": "Izaberi",
@ -93,13 +93,13 @@
"no_note_found": "Ne postoje spremljene napomene",
"insert_note": "Unesi bilješku",
"copied_pdf_url_clipboard": "Link do PDF fajla kopiran!",
"copied_url_clipboard": "URL je kopiran u međuspremnik!",
"docs": "Dokumenti",
"do_you_wish_to_continue": "Želite li nastaviti?",
"note": "Bilješka",
"pay_invoice": "Plati račun",
"login_successfully": "Uspješno ste prijavljeni!\n",
"logged_out_successfully": "Uspješno odjavljen\n",
"copied_url_clipboard": "Copied url to clipboard!",
"docs": "Docs",
"do_you_wish_to_continue": "Do you wish to continue?",
"note": "Note",
"pay_invoice": "Pay Invoice",
"login_successfully": "Logged in successfully!",
"logged_out_successfully": "Logged out successfully",
"mark_as_default": "Postavi kao zadano"
},
"dashboard": {
@ -109,7 +109,7 @@
"customers": "Klijenti",
"invoices": "Računi",
"estimates": "Ponude",
"payments": "Plaćanja"
"payments": "Payments"
},
"chart_info": {
"total_sales": "Prodaja",
@ -151,18 +151,18 @@
"no_results_found": "Nema rezultata"
},
"company_switcher": {
"label": "IZABERI TVRTKU",
"no_results_found": "Nema rezultata\n",
"add_new_company": "Dodajte novu tvrtku\n",
"new_company": "Nova tvrtka\n",
"created_message": "Tvrtka uspješno stvorena\n"
"label": "SWITCH COMPANY",
"no_results_found": "No Results Found",
"add_new_company": "Add new company",
"new_company": "New company",
"created_message": "Company created successfully"
},
"dateRange": {
"today": "Danas\n",
"this_week": "Danas\n",
"this_month": "Danas\n",
"this_quarter": "Danas\n",
"this_year": "Danas\n",
"today": "Today",
"this_week": "This Week",
"this_month": "This Month",
"this_quarter": "This Quarter",
"this_year": "This Year",
"previous_week": "Previous Week",
"previous_month": "Previous Month",
"previous_quarter": "Previous Quarter",
@ -456,32 +456,32 @@
"months": "{months} Month",
"years": "{years} Year",
"all": "All",
"paid": "Plaćeno",
"unpaid": "Ne plaćeno",
"viewed": "Pregledano",
"overdue": "Kašnjenja",
"active": "Aktivno",
"completed": "Završeno",
"customer": "KUPAC",
"paid_status": "STATUS PLAĆANJA",
"ref_no": "BR. REFERENCE",
"number": "BROJ",
"paid": "Paid",
"unpaid": "Unpaid",
"viewed": "Viewed",
"overdue": "Overdue",
"active": "Active",
"completed": "Completed",
"customer": "CUSTOMER",
"paid_status": "PAID STATUS",
"ref_no": "REF NO.",
"number": "NUMBER",
"amount_due": "AMOUNT DUE",
"partially_paid": "Djelomično plaćeno\n",
"total": "Ukupno",
"discount": "Popust",
"sub_total": "Popdzbroj",
"invoice": "Ponavljajuća faktura | Ponavjaljuća faktura",
"invoice_number": "Broj ponavljajuće fakture\n",
"next_invoice_date": "Datum sljedećeg računa",
"ref_number": "Broj reference",
"contact": "Kontakt",
"add_item": "Dodaj stavku",
"date": "Datum",
"limit_by": "Ograniči po",
"limit_date": "Vremenski rok",
"limit_count": "Broj ograničenja\n",
"count": "Brojač",
"partially_paid": "Partially Paid",
"total": "Total",
"discount": "Discount",
"sub_total": "Sub Total",
"invoice": "Recurring Invoice | Recurring Invoices",
"invoice_number": "Recurring Invoice Number",
"next_invoice_date": "Next Invoice Date",
"ref_number": "Ref Number",
"contact": "Contact",
"add_item": "Add an Item",
"date": "Date",
"limit_by": "Limit by",
"limit_date": "Limit Date",
"limit_count": "Limit Count",
"count": "Count",
"status": "Status",
"select_a_status": "Select a status",
"working": "Working",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Ponuda",
"pdf_estimate_number": "Broj Ponude",
"pdf_estimate_date": "Datum Ponude",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Datum isteka Ponude",
"pdf_invoice_label": "Faktura",
"pdf_invoice_number": "Broj Fakture",
"pdf_invoice_date": "Datum Fakture",

File diff suppressed because it is too large Load Diff

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Estimate",
"pdf_estimate_number": "Estimate Number",
"pdf_estimate_date": "Estimate Date",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Expiry date",
"pdf_invoice_label": "Invoice",
"pdf_invoice_number": "Invoice Number",
"pdf_invoice_date": "Invoice Date",

View File

@ -17,6 +17,7 @@ import sk from './sk.json'
import vi from './vi.json'
import el from './el.json'
import hr from './hr.json'
import th from './th.json'
export default {
cs,
@ -37,5 +38,6 @@ export default {
vi,
pl,
el,
hr
hr,
th
}

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Pasiūlymas",
"pdf_estimate_number": "Pasiūlymo numeris",
"pdf_estimate_date": "Pasiūlymo data",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Galiojimo laikas",
"pdf_invoice_label": "Sąskaita",
"pdf_invoice_number": "Invoice Number",
"pdf_invoice_date": "Invoice Date",

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
"customers": "Klanten",
"items": "Artikelen",
"invoices": "Facturen",
"recurring-invoices": "Periodieke facturen",
"recurring-invoices": "Periodieke factuur",
"expenses": "Uitgaven",
"estimates": "Offertes",
"payments": "Betalingen",
@ -28,16 +28,16 @@
"from_date": "Vanaf datum",
"to_date": "T/m datum",
"from": "Vanaf",
"to": "Naar",
"ok": "Oké",
"yes": "Ja",
"no": "Nee",
"to": "Naar.",
"ok": "Oké.",
"yes": "Ja.",
"no": "Nee.",
"sort_by": "Sorteer op",
"ascending": "Oplopend",
"descending": "Aflopend",
"subject": "Onderwerp",
"body": "Inhoud",
"message": "Bericht",
"message": "Bericht.",
"send": "Verstuur",
"preview": "Voorbeeld",
"go_back": "Ga terug",
@ -54,7 +54,7 @@
"actions": "Acties",
"subtotal": "SUBTOTAAL",
"discount": "KORTING",
"fixed": "Vast bedrag",
"fixed": "Gemaakt",
"percentage": "Percentage",
"tax": "BELASTING",
"total_amount": "TOTAALBEDRAG",
@ -85,17 +85,17 @@
"select_state": "Selecteer staat",
"select_country": "Selecteer land",
"select_city": "Selecteer stad",
"street_1": "Straat 1",
"street_2": "Straat 2",
"action_failed": "Actie mislukt",
"retry": "Opnieuw proberen",
"street_1": "straat 1",
"street_2": "Straat # 2",
"action_failed": "Actie: mislukt",
"retry": "Retr",
"choose_note": "Kies notitie",
"no_note_found": "Geen notitie gevonden",
"insert_note": "Notitie invoegen",
"copied_pdf_url_clipboard": "PDF link naar klembord gekopieerd!",
"copied_url_clipboard": "URL naar klembord gekopieerd!",
"docs": "Documentatie",
"do_you_wish_to_continue": "Wil je doorgaan?",
"docs": "Documenten",
"do_you_wish_to_continue": "Wilt u Doorgaan?",
"note": "Notitie",
"pay_invoice": "Betaal factuur",
"login_successfully": "Succesvol ingelogd!",
@ -526,7 +526,7 @@
"cloned_successfully": "Terugkerende factuur succesvol gekopieerd",
"clone_invoice": "Kopieer periodieke factuur",
"confirm_clone": "Deze periodieke factuur wordt gekopieerd naar een nieuwe periodieke factuur",
"add_customer_email": "Voeg een e-mailadres aan deze klant toe zodat facturen automatisch verzonden kunnen worden.",
"add_customer_email": "Voeg een e-mailadres aan deze klant toe, zodat facturen automatisch verzonden kunnen worden.",
"item": {
"title": "Item titel",
"description": "Beschrijving",
@ -1114,13 +1114,13 @@
"exchange_help_text": "Voer de wisselkoers in om te converteren van {currency} naar {baseCurrency}",
"currency_freak": "Valuta Freak",
"currency_layer": "Valuta-laag",
"open_exchange_rate": "Open wisselkoers",
"open_exchange_rate": "Open Exchange Rate",
"currency_converter": "Valuta omzetter",
"server": "Server",
"url": "URL",
"active": "Actief",
"currency_help_text": "Deze aanbieder wordt alleen gebruikt voor de hier boven geselecteerde valuta",
"currency_in_used": "De volgende valuta zijn al actief bij een andere aanbieder. Verwijder deze valuta uit de selectie om deze aanbieder opnieuw te activeren."
"currency_help_text": "This provider will only be used on above selected currencies",
"currency_in_used": "The following currencies are already active on another provider. Please remove these currencies from selection to activate this provider again."
},
"tax_types": {
"title": "Belastingtypen",
@ -1143,16 +1143,16 @@
},
"payment_modes": {
"title": "Betaalmethodes",
"description": "Modi van transacties voor betalingen",
"add_payment_mode": "Voeg betaalwijze toe",
"edit_payment_mode": "Wijzig betaalwijze",
"mode_name": "Modusnaam",
"description": "Modes of transaction for payments",
"add_payment_mode": "Add Payment Mode",
"edit_payment_mode": "Edit Payment Mode",
"mode_name": "Mode Name",
"payment_mode_added": "Betaalwijze toegevoegd",
"payment_mode_updated": "Betaalwijze bijgewerkt",
"payment_mode_confirm_delete": "U kunt deze betalingsmodus niet herstellen",
"payments_attached": "Deze betalingsmethode is al gekoppeld aan betalingen. Verwijder de gekoppelde betalingen om verder te gaan met het verwijderen.",
"expenses_attached": "Deze betaalmethode is al gekoppeld aan uitgaven. Verwijder de gekoppelde kosten om door te gaan met het verwijderen.",
"deleted_message": "Betaalwijze succesvol verwijderd"
"payment_mode_updated": "Payment Mode Updated",
"payment_mode_confirm_delete": "You will not be able to recover this Payment Mode",
"payments_attached": "This payment method is already attached to payments. Please delete the attached payments to proceed with deletion.",
"expenses_attached": "This payment method is already attached to expenses. Please delete the attached expenses to proceed with deletion.",
"deleted_message": "Payment Mode deleted successfully"
},
"expense_category": {
"title": "Onkostencategorieën",
@ -1178,8 +1178,8 @@
"discount_setting": "Kortingsinstelling",
"discount_per_item": "Korting per item",
"discount_setting_description": "Schakel dit in als u korting wilt toevoegen aan afzonderlijke factuuritems. Standaard wordt korting rechtstreeks aan de factuur toegevoegd.",
"expire_public_links": "Publieke links automatisch laten vervallen",
"expire_setting_description": "Geef aan of je alle links die eerder zijn verstuurd door de applicatie om facturen, offertes en betalingen te bekijken wilt laten verlopen na een bepaalde duur.",
"expire_public_links": "Automatically Expire Public Links",
"expire_setting_description": "Specify whether you would like to expire all the links sent by application to view invoices, estimates & payments, etc after a specified duration.",
"save": "Opslaan",
"preference": "Voorkeur | Voorkeuren",
"general_settings": "Standaardvoorkeuren voor het systeem.",
@ -1188,9 +1188,9 @@
"select_time_zone": "Selecteer Tijdzone",
"select_date_format": "Selecteer datum/tijdindeling",
"select_financial_year": "Selecteer financieel ja",
"recurring_invoice_status": "Status periodieke facturen",
"create_status": "Status aanmaken",
"active": "Actief",
"recurring_invoice_status": "Recurring Invoice Status",
"create_status": "Create Status",
"active": "Active",
"on_hold": "In wacht",
"update_status": "Updatestatus",
"completed": "Voltooid",
@ -1217,10 +1217,10 @@
"finishing_update": "Afwerking Update",
"update_failed": "Update mislukt",
"update_failed_text": "Sorry! Je update is mislukt op: {step} step ",
"update_warning": "Alle applicatiebestanden en de standaard sjabloonbestanden worden overschreven wanneer u de applicatie met behulp van dit hulpprogramma bijwerkt. Maak een reservekopie van uw sjablonen en database voordat u deze bijwerkt."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
},
"backup": {
"title": "Back-up | Back-ups",
"title": "Backup | Backups",
"description": "De back-up is een zipfile met alle bestanden in de mappen die je opgeeft samen met een dump van je database",
"new_backup": "Nieuwe back-up",
"create_backup": "Backup maken",

View File

@ -2,7 +2,7 @@
"navigation": {
"dashboard": "Pulpit",
"customers": "Kontrahenci",
"items": "Produkty",
"items": "Pozycje",
"invoices": "Faktury",
"recurring-invoices": "Faktury cykliczne",
"expenses": "Wydatki",
@ -100,7 +100,7 @@
"pay_invoice": "Zapłać Fakturę",
"login_successfully": "Zalogowano pomyślnie!",
"logged_out_successfully": "Wylogowano pomyślnie",
"mark_as_default": "Oznacz jako domyślne"
"mark_as_default": "Mark as default"
},
"dashboard": {
"select_year": "Wybierz rok",
@ -355,7 +355,7 @@
"select_an_item": "Wpisz lub kliknij aby wybrać element",
"type_item_description": "Opis pozycji (opcjonalnie)"
},
"mark_as_default_estimate_template_description": "Jeśli włączone, wybrany szablon zostanie automatycznie wybrany dla nowych ofert."
"mark_as_default_estimate_template_description": "If enabled, the selected template will be automatically selected for new estimates."
},
"invoices": {
"title": "Faktury",
@ -447,7 +447,7 @@
"marked_as_sent_message": "Faktura oznaczona jako wysłana pomyślnie",
"something_went_wrong": "coś poszło nie tak",
"invalid_due_amount_message": "Całkowita kwota faktury nie może być mniejsza niż całkowita kwota zapłacona za tę fakturę. Proszę zaktualizować fakturę lub usunąć powiązane płatności, aby kontynuować.",
"mark_as_default_invoice_template_description": "Jeśli włączone, wybrany szablon zostanie automatycznie wybrany dla nowych faktur."
"mark_as_default_invoice_template_description": "If enabled, the selected template will be automatically selected for new invoices."
},
"recurring_invoices": {
"title": "Faktury cykliczne",
@ -526,7 +526,7 @@
"cloned_successfully": "Faktura Cykliczna sklonowana pomyślnie",
"clone_invoice": "Klonuj Fakturę Cykliczną",
"confirm_clone": "Ta faktura cykliczna zostanie sklonowana do nowej faktury cyklicznej",
"add_customer_email": "Dodaj adres e-mail dla tego klienta, aby wysyłać faktury automatycznie.",
"add_customer_email": "Please add an email address for this customer to send invoices automatically.",
"item": {
"title": "Tytuł pozycji",
"description": "Opis",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Oferta",
"pdf_estimate_number": "Numer oferty",
"pdf_estimate_date": "Data oferty",
"pdf_estimate_expire_date": "Data ważności",
"pdf_estimate_expire_date": "Termin ważności",
"pdf_invoice_label": "Faktura",
"pdf_invoice_number": "Numer faktury",
"pdf_invoice_date": "Data faktury",

View File

@ -12,7 +12,7 @@
"settings": "Configurações",
"logout": "Encerrar sessão",
"users": "Usuários",
"modules": "Módulos"
"modules": "Navegação → módulos"
},
"general": {
"add_company": "Adicionar Empresa",
@ -29,13 +29,13 @@
"to_date": "Até a Data",
"from": "De",
"to": "Para",
"ok": "Ok",
"ok": "Geral → Ok",
"yes": "Sim",
"no": "Não",
"sort_by": "Ordenar por",
"ascending": "Crescente",
"descending": "Descendente",
"subject": "Assunto",
"subject": "Sujeita",
"body": "Corpo",
"message": "Mensagem",
"send": "Enviar",
@ -210,8 +210,8 @@
"basic_info": "Informação Básica",
"portal_access": "Clientes → Acessar portal",
"portal_access_text": "Clientes→ Texto do portal de acesso?",
"portal_access_url": "URL de login do Portal do Cliente",
"portal_access_url_help": "Por favor, copie a URL fornecida acima e envie a seu cliente para fornecer acesso.",
"portal_access_url": "Customer Portal Login URL",
"portal_access_url_help": "Please copy & forward the above given URL to your customer for providing access.",
"billing_address": "Endereço de cobrança",
"shipping_address": "Endereço de entrega",
"copy_billing_address": "Copiar Endereço de Faturamento",
@ -231,7 +231,7 @@
"confirm_delete": "Você não poderá recuperar este cliente e todas as faturas, orçamentos e pagamentos relacionados. | Você não poderá recuperar esses clientes e todas as faturas, estimativas e pagamentos relacionados.",
"created_message": "Cliente criado com sucesso",
"updated_message": "Cliente atualizado com sucesso",
"address_updated_message": "Informações de endereço atualizadas com sucesso",
"address_updated_message": "Address Information Updated succesfully",
"deleted_message": "Cliente excluído com sucesso | Clientes excluídos com sucesso",
"edit_currency_not_allowed": "Não é possível alterar a moeda depois de criar transações."
},
@ -265,8 +265,8 @@
},
"estimates": {
"title": "Orçamentos",
"accept_estimate": "Aceitar Orçamento",
"reject_estimate": "Rejeitar Orçamento",
"accept_estimate": "Accept Estimate",
"reject_estimate": "Reject Estimate",
"estimate": "Orçamento | Orçamentos",
"estimates_list": "Lista de orçamentos",
"days": "{days} Dias",
@ -318,10 +318,10 @@
},
"accepted": "Aceito",
"rejected": "Rejeitado",
"expired": "Expirado",
"expired": "Expired",
"sent": "Enviado",
"draft": "Rascunho",
"viewed": "Visualizado",
"viewed": "Viewed",
"declined": "Rejeitado",
"new_estimate": "Novo orçamento",
"add_new_estimate": "Adicionar novo orçamento",
@ -355,14 +355,14 @@
"select_an_item": "Escreva ou clique para selecionar um item",
"type_item_description": "Descrição do Item (opcional)"
},
"mark_as_default_estimate_template_description": "Se habilitado, o modelo selecionado será automaticamente selecionado para novas estimativas."
"mark_as_default_estimate_template_description": "If enabled, the selected template will be automatically selected for new estimates."
},
"invoices": {
"title": "Faturas",
"download": "Baixar",
"pay_invoice": "Pagar Fatura",
"download": "Download",
"pay_invoice": "Pay Invoice",
"invoices_list": "Lista de faturas",
"invoice_information": "Informações da Fatura",
"invoice_information": "Invoice Information",
"days": "{days} dias",
"months": "{months} Mês",
"years": "{years} Ano",
@ -374,7 +374,7 @@
"completed": "Concluído",
"customer": "CLIENTE",
"paid_status": "STATUS PAGAMENTO",
"ref_no": "N° de Referência",
"ref_no": "REF NO.",
"number": "NÚMERO",
"amount_due": "VALOR DEVIDO",
"partially_paid": "Parcialmente Pago",
@ -447,7 +447,7 @@
"marked_as_sent_message": "Fatura marcada como enviada com sucesso",
"something_went_wrong": "algo deu errado",
"invalid_due_amount_message": "O valor total da fatura não pode ser menor que o valor total pago para esta fatura. Atualize a fatura ou exclua os pagamentos associados para continuar.",
"mark_as_default_invoice_template_description": "Se habilitado, o modelo selecionado será automaticamente selecionado para novas estimativas."
"mark_as_default_invoice_template_description": "If enabled, the selected template will be automatically selected for new invoices."
},
"recurring_invoices": {
"title": "Faturas Recorrentes",
@ -464,56 +464,56 @@
"completed": "Concluído",
"customer": "CLIENTE",
"paid_status": "STATUS PAGAMENTO",
"ref_no": "N° de Referência",
"number": "NÚMERO",
"amount_due": "VALOR DEVIDO",
"partially_paid": "Parcialmente Pago",
"ref_no": "REF NO.",
"number": "NUMBER",
"amount_due": "AMOUNT DUE",
"partially_paid": "Partially Paid",
"total": "Total",
"discount": "Desconto",
"sub_total": "Subtotal",
"invoice": "Fatura Recorrente | Faturas Recorrentes",
"invoice_number": "Número da Fatura Recorrente",
"next_invoice_date": "Data da Próxima Fatura",
"ref_number": "Número de Referência",
"contact": "Contato",
"add_item": "Adicionar um Item",
"date": "Data",
"limit_by": "Limitar por",
"limit_date": "Data Limite",
"limit_count": "Quantidade Máxima",
"count": "Quantidade",
"discount": "Discount",
"sub_total": "Sub Total",
"invoice": "Recurring Invoice | Recurring Invoices",
"invoice_number": "Recurring Invoice Number",
"next_invoice_date": "Next Invoice Date",
"ref_number": "Ref Number",
"contact": "Contact",
"add_item": "Add an Item",
"date": "Date",
"limit_by": "Limit by",
"limit_date": "Limit Date",
"limit_count": "Limit Count",
"count": "Count",
"status": "Status",
"select_a_status": "Selecione o Status",
"working": "Processando",
"on_hold": "Pausado",
"complete": "Concluído",
"add_tax": "Adicionar Imposto",
"amount": "Valor",
"action": "Ação",
"notes": "Observações",
"view": "Ver",
"basic_info": "Informações Básicas",
"send_invoice": "Enviar Fatura Recorrente",
"auto_send": "Envio Automático",
"resend_invoice": "Reenviar Fatura Recorrente",
"invoice_template": "Modelo de Fatura Recorrente",
"conversion_message": "Fatura Recorrente clonada com sucesso",
"template": "Modelo",
"mark_as_sent": "Marcar como enviado",
"confirm_send_invoice": "Esta fatura recorrente será enviada por e-mail para o cliente",
"invoice_mark_as_sent": "Esta fatura recorrente será marcada como enviada",
"confirm_send": "Esta fatura recorrente será enviada por e-mail para o cliente",
"starts_at": "Data de início",
"due_date": "Vencimento da Fatura",
"record_payment": "Registrar Pagamento",
"add_new_invoice": "Adicionar nova fatura recorrente",
"update_expense": "Atualizar Despesa",
"edit_invoice": "Editar fatura recorrente",
"new_invoice": "Nova fatura recorrente",
"send_automatically": "Enviar automaticamente",
"send_automatically_desc": "Habilite isso, se você gostaria de enviar a fatura automaticamente para o cliente.",
"save_invoice": "Salvar fatura recorrente",
"update_invoice": "Atualizar fatura recorrente",
"select_a_status": "Select a status",
"working": "Working",
"on_hold": "On Hold",
"complete": "Completed",
"add_tax": "Add Tax",
"amount": "Amount",
"action": "Action",
"notes": "Notes",
"view": "View",
"basic_info": "Basic Info",
"send_invoice": "Send Recurring Invoice",
"auto_send": "Auto Send",
"resend_invoice": "Resend Recurring Invoice",
"invoice_template": "Recurring Invoice Template",
"conversion_message": "Recurring Invoice cloned successful",
"template": "Template",
"mark_as_sent": "Mark as sent",
"confirm_send_invoice": "This recurring invoice will be sent via email to the customer",
"invoice_mark_as_sent": "This recurring invoice will be marked as sent",
"confirm_send": "This recurring invoice will be sent via email to the customer",
"starts_at": "Start Date",
"due_date": "Invoice Due Date",
"record_payment": "Record Payment",
"add_new_invoice": "Add New Recurring Invoice",
"update_expense": "Update Expense",
"edit_invoice": "Edit Recurring Invoice",
"new_invoice": "New Recurring Invoice",
"send_automatically": "Send Automatically",
"send_automatically_desc": "Enable this, if you would like to send the invoice automatically to the customer when its created.",
"save_invoice": "Save Recurring Invoice",
"update_invoice": "Update Recurring Invoice",
"add_new_tax": "Adicionar Novo Imposto",
"no_invoices": "Não há faturas recorrentes ainda!",
"mark_as_rejected": "Marcar como rejeitada",
@ -522,42 +522,42 @@
"select_invoice": "Selecionar Fatura",
"no_matching_invoices": "Não há faturas recorrentes correspondentes!",
"mark_as_sent_successfully": "Fatura recorrente marcada como enviada com sucesso",
"invoice_sent_successfully": "Fatura recorrente enviada com sucesso",
"cloned_successfully": "Fatura recorrente copiada com sucesso",
"clone_invoice": "Copiar Fatura Recorrente",
"confirm_clone": "Esta fatura recorrente será copiada em uma nova fatura recorrente",
"add_customer_email": "Por favor, adicione um endereço de e-mail para este cliente para enviar faturas automaticamente.",
"invoice_sent_successfully": "Recurring Invoice sent successfully",
"cloned_successfully": "Recurring Invoice cloned successfully",
"clone_invoice": "Clone Recurring Invoice",
"confirm_clone": "This recurring invoice will be cloned into a new Recurring Invoice",
"add_customer_email": "Please add an email address for this customer to send invoices automatically.",
"item": {
"title": "Titulo do item",
"description": "Descrição",
"quantity": "Quantidade",
"price": "Preço",
"discount": "Desconto",
"title": "Item Title",
"description": "Description",
"quantity": "Quantity",
"price": "Price",
"discount": "Discount",
"total": "Total",
"total_discount": "Desconto total",
"sub_total": "Subtotal",
"tax": "Imposto",
"amount": "Valor",
"select_an_item": "Digite ou clique para selecionar",
"type_item_description": "Descrição do Item (opcional)"
"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)"
},
"frequency": {
"title": "Frequência",
"select_frequency": "Selecione a Frequência",
"minute": "Minuto",
"hour": "Hora",
"day_month": "Dia do mês",
"month": "Mês",
"day_week": "Dia da semana"
"title": "Frequency",
"select_frequency": "Select Frequency",
"minute": "Minute",
"hour": "Hour",
"day_month": "Day of month",
"month": "Month",
"day_week": "Day of week"
},
"confirm_delete": "Você não poderá recuperar esta fatura | Você não poderá recuperar essas faturas",
"created_message": "Fatura recorrente criada com sucesso",
"updated_message": "Fatura recorrente atualizada com sucesso",
"deleted_message": "Fatura recorrente excluída com sucesso | Faturas recorrentes excluídas com sucesso",
"marked_as_sent_message": "Fatura recorrente marcada como enviada com sucesso",
"user_email_does_not_exist": "E-mail de usuário não existe",
"something_went_wrong": "houve algo de errado",
"invalid_due_amount_message": "O valor total da fatura não pode ser menor que o valor total pago para esta fatura. Atualize a fatura ou exclua os pagamentos associados para continuar."
"confirm_delete": "You will not be able to recover this Invoice | You will not be able to recover these Invoices",
"created_message": "Recurring Invoice created successfully",
"updated_message": "Recurring Invoice updated successfully",
"deleted_message": "Recurring Invoice deleted successfully | Recurring Invoices deleted successfully",
"marked_as_sent_message": "Recurring 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 Recurring Invoice amount cannot be less than total paid amount for this Recurring Invoice. Please update the invoice or delete the associated payments to continue."
},
"payments": {
"title": "Pagamentos",
@ -603,7 +603,7 @@
"select_a_customer": "Selecione um cliente",
"expense_title": "Título",
"customer": "Cliente",
"currency": "Moeda",
"currency": "Currency",
"contact": "Contato",
"category": "Categoria",
"from_date": "A partir da Data",
@ -658,49 +658,49 @@
"retype_password": "Confirme a Senha"
},
"modules": {
"buy_now": "Compre agora",
"install": "Instalar",
"price": "Preço",
"download_zip_file": "Baixar arquivo ZIP",
"unzipping_package": "Descompactando pacote",
"copying_files": "Copiando arquivos",
"deleting_files": "Excluindo arquivos não utilizados",
"completing_installation": "Completando instalação",
"update_failed": "Atualização falhou",
"install_success": "Módulo foi instalado com sucesso!",
"customer_reviews": "Avaliações",
"license": "Licença",
"buy_now": "Buy Now",
"install": "Install",
"price": "Price",
"download_zip_file": "Download ZIP file",
"unzipping_package": "Unzipping Package",
"copying_files": "Copying Files",
"deleting_files": "Deleting Unused files",
"completing_installation": "Completing Installation",
"update_failed": "Update Failed",
"install_success": "Module has been installed successfully!",
"customer_reviews": "Reviews",
"license": "License",
"faq": "FAQ",
"monthly": "Mensalmente",
"yearly": "Anual",
"updated": "Atualizado",
"version": "Versão",
"disable": "Desabilitar",
"module_disabled": "Módulo Desabilitado",
"enable": "Habilitar",
"module_enabled": "Módulo Habilitado",
"update_to": "Atualizar Para",
"module_updated": "Módulo atualizado com sucesso!",
"title": "Módulos",
"module": "Módulo | Módulos",
"api_token": "Token de API",
"invalid_api_token": "Token da API inválido.",
"other_modules": "Outros Módulos",
"view_all": "Ver todos",
"no_reviews_found": "Não há avaliações para este módulo ainda!",
"module_not_purchased": "Módulo não comprado",
"module_not_found": "Módulo não encontrado",
"monthly": "Monthly",
"yearly": "Yearly",
"updated": "Updated",
"version": "Version",
"disable": "Disable",
"module_disabled": "Module Disabled",
"enable": "Enable",
"module_enabled": "Module Enabled",
"update_to": "Update To",
"module_updated": "Module Updated Successfully!",
"title": "Modules",
"module": "Module | Modules",
"api_token": "API token",
"invalid_api_token": "Invalid API Token.",
"other_modules": "Other Modules",
"view_all": "View All",
"no_reviews_found": "There are no reviews for this module yet!",
"module_not_purchased": "Module Not Purchased",
"module_not_found": "Module Not Found",
"version_not_supported": "This module version doesn't support the current version of Crater",
"last_updated": "Última atualização em",
"connect_installation": "Conecte sua instalação",
"api_token_description": "Faça login em {url} e conecte esta instalação digitando o Token da API. Os módulos comprados aparecerão aqui após a conexão ser estabelecida.",
"view_module": "Ver Módulo",
"update_available": "Atualização disponível",
"purchased": "Comprado",
"installed": "Instalado",
"no_modules_installed": "Nenhum módulo instalado ainda!",
"disable_warning": "Todas as configurações serão revertidas.",
"what_you_get": "O que você recebe?"
"last_updated": "Last Updated On",
"connect_installation": "Connect your installation",
"api_token_description": "Login to {url} and connect this installation by entering the API Token. Your purchased modules will show up here after the connection is established.",
"view_module": "View Module",
"update_available": "Update Available",
"purchased": "Purchased",
"installed": "Installed",
"no_modules_installed": "No Modules Installed Yet!",
"disable_warning": "All the settings for this particular will be reverted.",
"what_you_get": "What you get"
},
"users": {
"title": "Usuários",
@ -727,8 +727,8 @@
"created_message": "Usuário criado com sucesso",
"updated_message": "Usuário atualizado com sucesso",
"deleted_message": "Usuário excluído com sucesso | Usuários excluídos com sucesso",
"select_company_role": "Selecione o cargo da {company}",
"companies": "Empresas"
"select_company_role": "Select Role for {company}",
"companies": "Companies"
},
"reports": {
"title": "Relatório",
@ -801,16 +801,16 @@
"tax_types": "Tipos de Impostos",
"expense_category": "Categorias de Despesas",
"update_app": "Atualizar Aplicativo",
"backup": "Cópia de Segurança",
"backup": "Backup",
"file_disk": "Disco de Arquivos",
"custom_fields": "Os campos personalizados",
"payment_modes": "Meios de Pagamento",
"notes": "Observações",
"exchange_rate": "Taxa de Câmbio",
"address_information": "Informações de Endereço"
"exchange_rate": "Exchange Rate",
"address_information": "Address Information"
},
"address_information": {
"section_description": " Você pode atualizar suas informações de endereço usando o formulário abaixo."
"section_description": " You can update Your Address information using form below."
},
"title": "Configurações",
"setting": "Configuração | Configurações",
@ -872,13 +872,13 @@
"address": "Endereço",
"zip": "CEP",
"save": "Salvar",
"delete": "Excluir",
"delete": "Delete",
"updated_message": "Informações da Empresa atualizadas com sucesso",
"delete_company": "Excluir Empresa",
"delete_company_description": "Depois de excluir sua empresa, você perderá todos os dados e arquivos associados a ela permanentemente.",
"are_you_absolutely_sure": "Você tem certeza?",
"delete_company_modal_desc": "Esta ação não pode ser desfeita. Isto irá apagar permanentemente a {company} e todos os dados associados.",
"delete_company_modal_label": "Digite {company} para confirmar"
"delete_company": "Delete Company",
"delete_company_description": "Once you delete your company, you will lose all the data and files associated with it permanently.",
"are_you_absolutely_sure": "Are you absolutely sure?",
"delete_company_modal_desc": "This action cannot be undone. This will permanently delete {company} and all of its associated data.",
"delete_company_modal_label": "Please type {company} to confirm"
},
"custom_fields": {
"title": "Os campos personalizados",
@ -916,103 +916,103 @@
"ticked_by_default": "Marcado por padrão",
"updated_message": "Campo personalizado atualizado com sucesso",
"added_message": "Campo personalizado adicionado com sucesso",
"press_enter_to_add": "Aperte enter para adicionar uma nova opção",
"model_in_use": "Não é possível atualizar o modelo para campos que já estão em uso.",
"type_in_use": "Não é possível atualizar o tipo para os campos que já estão em uso."
"press_enter_to_add": "Press enter to add new option",
"model_in_use": "Cannot update model for fields which are already in use.",
"type_in_use": "Cannot update type for fields which are already in use."
},
"customization": {
"customization": "personalização",
"updated_message": "Informações da Empresa atualizadas com sucesso",
"save": "Salvar",
"insert_fields": "Inserir Campos",
"learn_custom_format": "Aprenda a usar o formato personalizado",
"add_new_component": "Novo Componente",
"component": "Componente",
"Parameter": "Parâmetro",
"series": "Séries",
"series_description": "Para definir um prefixo/sufixo estático como 'INV' em sua empresa. Ele suporta o comprimento do caractere de até 6 caracteres.",
"series_param_label": "Valor da Série",
"delimiter": "Delimitador",
"delimiter_description": "Caractere único para especificar o limite entre 2 componentes separados. Por padrão é -",
"delimiter_param_label": "Valor Delimitador",
"date_format": "Formato de Data",
"date_format_description": "Um campo de data e hora local que aceita um parâmetro de formato. O formato padrão: 'Y' apresenta o ano atual.",
"date_format_param_label": "Formato",
"sequence": "Sequência",
"sequence_description": "Sequência consecutiva de números em sua empresa. Você pode especificar o comprimento nos parâmetros indicados.",
"sequence_param_label": "Comprimento da sequência",
"customer_series": "Série do Cliente",
"customer_series_description": "Para definir um prefixo/sufixo diferente para cada cliente.",
"customer_sequence": "Sequência do Cliente",
"customer_sequence_description": "Sequência consecutiva de números para cada um de seus clientes.",
"customer_sequence_param_label": "Comprimento da Sequência",
"random_sequence": "Sequência aleatória",
"random_sequence_description": "Cadeia alfanumérica aleatória. Você pode especificar o comprimento no parâmetro fornecido.",
"random_sequence_param_label": "Comprimento da Sequência",
"insert_fields": "Insert Fields",
"learn_custom_format": "Learn how to use custom format",
"add_new_component": "Add New Component",
"component": "Component",
"Parameter": "Parameter",
"series": "Series",
"series_description": "To set a static prefix/postfix like 'INV' across your company. It supports character length of up to 6 chars.",
"series_param_label": "Series Value",
"delimiter": "Delimiter",
"delimiter_description": "Single character for specifying the boundary between 2 separate components. By default its set to -",
"delimiter_param_label": "Delimiter Value",
"date_format": "Date Format",
"date_format_description": "A local date and time field which accepts a format parameter. The default format: 'Y' renders the current year.",
"date_format_param_label": "Format",
"sequence": "Sequence",
"sequence_description": "Consecutive sequence of numbers across your company. You can specify the length on the given parameter.",
"sequence_param_label": "Sequence Length",
"customer_series": "Customer Series",
"customer_series_description": "To set a different prefix/postfix for each customer.",
"customer_sequence": "Customer Sequence",
"customer_sequence_description": "Consecutive sequence of numbers for each of your customer.",
"customer_sequence_param_label": "Sequence Length",
"random_sequence": "Random Sequence",
"random_sequence_description": "Random alphanumeric string. You can specify the length on the given parameter.",
"random_sequence_param_label": "Sequence Length",
"invoices": {
"title": "Faturas",
"invoice_number_format": "Formato do Número da Fatura",
"invoice_number_format_description": "Personalize como o número da sua fatura é gerado automaticamente quando você cria uma nova fatura.",
"preview_invoice_number": "Pré-visualizar número da fatura",
"due_date": "Vencimento",
"due_date_description": "Especifique como a data de vencimento é definida automaticamente ao criar uma fatura.",
"due_date_days": "Número de dias antes do vencimento da fatura",
"set_due_date_automatically": "Definir Data de Vencimento Automaticamente",
"set_due_date_automatically_description": "Habilite isso se deseja definir a data de vencimento automaticamente ao criar uma fatura.",
"default_formats": "Formatos Padrão",
"default_formats_description": "Os formatos indicados abaixo são usados para preencher os campos automaticamente na criação da fatura.",
"invoice_number_format": "Invoice Number Format",
"invoice_number_format_description": "Customize how your invoice number gets generated automatically when you create a new invoice.",
"preview_invoice_number": "Preview Invoice Number",
"due_date": "Due Date",
"due_date_description": "Specify how due date is automatically set when you create an invoice.",
"due_date_days": "Invoice Due after days",
"set_due_date_automatically": "Set Due Date Automatically",
"set_due_date_automatically_description": "Enable this if you wish to set due date automatically when you create a new invoice.",
"default_formats": "Default Formats",
"default_formats_description": "Below given formats are used to fill up the fields automatically on invoice creation.",
"default_invoice_email_body": "Corpo Padrão de Email de Fatura",
"company_address_format": "Formato de Endereço de Empresa",
"shipping_address_format": "Formato de Endereço de Envio",
"billing_address_format": "Formato de Endereço de Faturamento",
"invoice_email_attachment": "Enviar faturas como anexos",
"invoice_email_attachment_setting_description": "Ative esta opção se quiser anexar faturas no e-mail. Lembrando que quando habilitado, o botão 'Ver fatura' nos e-mails não será mais exibido.",
"invoice_settings_updated": "Configurações da fatura atualizadas com sucesso",
"retrospective_edits": "Edições Retrospectivas",
"allow": "Permitir",
"disable_on_invoice_partial_paid": "Desativar após registrar um pagamento parcial",
"disable_on_invoice_paid": "Desativar após registrar um pagamento completo",
"disable_on_invoice_sent": "Desativar após o envio da fatura",
"retrospective_edits_description": " Com base nas leis do seu país ou na sua preferência, é possível restringir os usuários de editar faturas finalizadas."
"invoice_settings_updated": "Invoice Settings updated successfully",
"retrospective_edits": "Retrospective Edits",
"allow": "Allow",
"disable_on_invoice_partial_paid": "Disable after partial payment is recorded",
"disable_on_invoice_paid": "Disable after full payment is recorded",
"disable_on_invoice_sent": "Disable after invoice is sent",
"retrospective_edits_description": " Based on your country's laws or your preference, you can restrict users from editing finalised invoices."
},
"estimates": {
"title": "Orçamentos",
"estimate_number_format": "Formato do Número de Orçamento",
"estimate_number_format_description": "Personalize como seu número de orçamento é gerado automaticamente quando você cria um orçamento.",
"preview_estimate_number": "Pré-visualizar Número de Orçamento",
"expiry_date": "Vencimento",
"expiry_date_description": "Especifique como a data de vencimento é definida automaticamente quando você cria um orçamento.",
"expiry_date_days": "Orçamento expira após dias",
"set_expiry_date_automatically": "Definir Data de Vencimento Automaticamente",
"set_expiry_date_automatically_description": "Habilite isso se desejar definir a data de vencimento automaticamente ao criar um orçamento.",
"default_formats": "Formatos Padrão",
"default_formats_description": "Os formatos indicados abaixo são usados para preencher os campos automaticamente na criação do orçamento.",
"estimate_number_format": "Estimate Number Format",
"estimate_number_format_description": "Customize how your estimate number gets generated automatically when you create a new estimate.",
"preview_estimate_number": "Preview Estimate Number",
"expiry_date": "Expiry Date",
"expiry_date_description": "Specify how expiry date is automatically set when you create an estimate.",
"expiry_date_days": "Estimate Expires after days",
"set_expiry_date_automatically": "Set Expiry Date Automatically",
"set_expiry_date_automatically_description": "Enable this if you wish to set expiry date automatically when you create a new estimate.",
"default_formats": "Default Formats",
"default_formats_description": "Below given formats are used to fill up the fields automatically on estimate creation.",
"default_estimate_email_body": "Corpo Padrão de Email de Orçamento",
"company_address_format": "Formato de Endereço de Empresa",
"shipping_address_format": "Formato de Endereço de Envio",
"billing_address_format": "Formato de Endereço de Faturamento",
"estimate_email_attachment": "Enviar orçamentos como anexos",
"estimate_email_attachment_setting_description": "Ative esta opção se quiser anexar orçamentos no e-mail. Lembrando que quando habilitado, o botão 'Ver orçamento' nos e-mails não será mais exibido.",
"estimate_settings_updated": "Configurações de orçamento atualizadas com sucesso",
"convert_estimate_options": "Ação de Conversão de Orçamento",
"convert_estimate_description": "Especifique o que acontece com o orçamento depois que ele é convertido em uma fatura.",
"no_action": "Nenhuma ação",
"delete_estimate": "Excluir orçamento",
"mark_estimate_as_accepted": "Marcar orçamento como aceito"
"estimate_settings_updated": "Estimate Settings updated successfully",
"convert_estimate_options": "Estimate Convert Action",
"convert_estimate_description": "Specify what happens to the estimate after it gets converted to an invoice.",
"no_action": "No action",
"delete_estimate": "Delete estimate",
"mark_estimate_as_accepted": "Mark estimate as accepted"
},
"payments": {
"title": "Pagamentos",
"payment_number_format": "Formato do Número de Pagamento",
"payment_number_format_description": "Personalize como seu número de pagamento é gerado automaticamente quando você cria um pagamento.",
"preview_payment_number": "Visualizar Número de Pagamento",
"default_formats": "Formato padrão",
"default_formats_description": "Os formatos abaixo são usados para preencher os campos automaticamente na criação de pagamentos.",
"payment_number_format": "Payment Number Format",
"payment_number_format_description": "Customize how your payment number gets generated automatically when you create a new payment.",
"preview_payment_number": "Preview Payment Number",
"default_formats": "Default Formats",
"default_formats_description": "Below given formats are used to fill up the fields automatically on payment creation.",
"default_payment_email_body": "Corpo Padrão de Email de Pagamento",
"company_address_format": "Formato de Endereço de Empresa",
"from_customer_address_format": "Formato de Endereço de Cliente Remetente",
"payment_email_attachment": "Enviar pagamentos como anexos",
"payment_email_attachment_setting_description": "Ative esta opção se quiser enviar em anexo os recibos de pagamento no e-mail. Lembrando que quando habilitado, o botão 'Ver Pagamento' nos e-mails não será mais exibido.",
"payment_settings_updated": "Configurações de Pagamento atualizada com sucesso"
"payment_settings_updated": "Payment Settings updated successfully"
},
"items": {
"title": "Itens",
@ -1072,55 +1072,55 @@
"please_enter_email": "Por favor digite um E-mail"
},
"roles": {
"title": "Nível de Acesso",
"description": "Gerenciar os cargos e permissões desta empresa",
"save": "Salvar",
"add_new_role": "Criar Nível de Acesso",
"role_name": "Nome",
"added_on": "Adicionado em",
"add_role": "Adicionar função",
"edit_role": "Editar Função",
"name": "Nome",
"permission": "Permissão | Permissões",
"select_all": "Selecionar tudo",
"none": "Nenhum",
"confirm_delete": "Você não poderá recuperar este Cargo",
"created_message": "Cargo criado com sucesso",
"updated_message": "Cargo atualizado com sucesso",
"deleted_message": "Cargo deletado com sucesso",
"already_in_use": "Cargo já em uso"
"title": "Roles",
"description": "Manage the roles & permissions of this company",
"save": "Save",
"add_new_role": "Add New Role",
"role_name": "Role Name",
"added_on": "Added on",
"add_role": "Add Role",
"edit_role": "Edit Role",
"name": "Name",
"permission": "Permission | Permissions",
"select_all": "Select All",
"none": "None",
"confirm_delete": "You will not be able to recover this Role",
"created_message": "Role created successfully",
"updated_message": "Role updated successfully",
"deleted_message": "Role deleted successfully",
"already_in_use": "Role is already in use"
},
"exchange_rate": {
"exchange_rate": "Taxa de Câmbio",
"title": "Corrigir problemas do câmbio",
"description": "Por favor, indique a taxa de câmbio de todas as moedas mencionadas abaixo para ajudar o Crater a calcular corretamente as quantidades em {currency}.",
"exchange_rate": "Exchange Rate",
"title": "Fix Currency Exchange issues",
"description": "Please enter exchange rate of all the currencies mentioned below to help Crater properly calculate the amounts in {currency}.",
"drivers": "Drivers",
"new_driver": "Adicionar Fornecedor",
"edit_driver": "Editar fornecedor",
"new_driver": "Add New Provider",
"edit_driver": "Edit Provider",
"select_driver": "Select Driver",
"update": "selecione a taxa de câmbio ",
"providers_description": "Configure aqui a taxa de câmbio de seus fornecedores para buscar automaticamente a taxa de câmbio mais recente nas transações.",
"key": "Chave da API",
"name": "Nome",
"update": "select exchange rate ",
"providers_description": "Configure your exchange rate providers here to automatically fetch the latest exchange rate on transactions.",
"key": "API Key",
"name": "Name",
"driver": "Driver",
"is_default": "É PADRÃO",
"currency": "Moedas",
"is_default": "IS DEFAULT",
"currency": "Currencies",
"exchange_rate_confirm_delete": "You will not be able to recover this driver",
"created_message": "Fornecedor criado com sucesso",
"updated_message": "Fornecedor Atualizado com Sucesso",
"deleted_message": "Fornecedor Excluído com Sucesso",
"created_message": "Provider Created successfully",
"updated_message": "Provider Updated Successfully",
"deleted_message": "Provider Deleted Successfully",
"error": " You cannot Delete Active Driver",
"default_currency_error": "Esta moeda já é usada em um dos fornecedores ativos",
"exchange_help_text": "Digite a taxa de câmbio para converter de {currency} para {baseCurrency}",
"default_currency_error": "This currency is already used in one of the Active Provider",
"exchange_help_text": "Enter exchange rate to convert from {currency} to {baseCurrency}",
"currency_freak": "Currency Freak",
"currency_layer": "Currency Layer",
"open_exchange_rate": "Abrir Taxa de Câmbio",
"currency_converter": "Conversor de moeda",
"server": "Servidor",
"open_exchange_rate": "Open Exchange Rate",
"currency_converter": "Currency Converter",
"server": "Server",
"url": "URL",
"active": "Ativo",
"currency_help_text": "Este fornecedor será usado somente nas moedas selecionadas acima",
"currency_in_used": "As seguintes moedas já estão ativas em outro fornecedor. Remova essas moedas da seleção para ativar este fornecedor novamente."
"active": "Active",
"currency_help_text": "This provider will only be used on above selected currencies",
"currency_in_used": "The following currencies are already active on another provider. Please remove these currencies from selection to activate this provider again."
},
"tax_types": {
"title": "Tipos de Impostos",
@ -1142,17 +1142,17 @@
"already_in_use": "O Imposto já está em uso"
},
"payment_modes": {
"title": "Forma de Pagamento",
"description": "Modos de transação para pagamentos",
"add_payment_mode": "Adicionar Forma de Pagamento",
"edit_payment_mode": "Editar Forma de Pagamento",
"mode_name": "Nome da Forma de Pagamento",
"payment_mode_added": "Forma de Pagamento Adicionada",
"payment_mode_updated": "Forma de Pagamento Atualizada",
"payment_mode_confirm_delete": "Você não poderá recuperar esta Forma de Pagamento",
"payments_attached": "Este método de pagamento já está anexado aos pagamentos. Por favor, exclua os pagamentos anexados para prosseguir com a exclusão.",
"expenses_attached": "Este método de pagamento já está anexado às despesas. Por favor, apague as despesas anexadas para prosseguir com a exclusão.",
"deleted_message": "Forma de Pagamento excluída com sucesso"
"title": "Payment Modes",
"description": "Modes of transaction for payments",
"add_payment_mode": "Add Payment Mode",
"edit_payment_mode": "Edit Payment Mode",
"mode_name": "Mode Name",
"payment_mode_added": "Payment Mode Added",
"payment_mode_updated": "Payment Mode Updated",
"payment_mode_confirm_delete": "You will not be able to recover this Payment Mode",
"payments_attached": "This payment method is already attached to payments. Please delete the attached payments to proceed with deletion.",
"expenses_attached": "This payment method is already attached to expenses. Please delete the attached expenses to proceed with deletion.",
"deleted_message": "Payment Mode deleted successfully"
},
"expense_category": {
"title": "Categoria de Despesa",
@ -1178,8 +1178,8 @@
"discount_setting": "Configuração de Desconto",
"discount_per_item": "Desconto por Item ",
"discount_setting_description": "Habilite isso se desejar adicionar desconto a itens de Fatura individualmente. Por padrão, o desconto é adicionado diretamente à Fatura.",
"expire_public_links": "Expirar Links Públicos Automaticamente",
"expire_setting_description": "Especifique se deseja expirar todos os links enviados pelo aplicativo para visualizar faturas, orçamentos, pagamentos e etc., após um período especificado.",
"expire_public_links": "Automatically Expire Public Links",
"expire_setting_description": "Specify whether you would like to expire all the links sent by application to view invoices, estimates & payments, etc after a specified duration.",
"save": "Salvar",
"preference": "Preferência | Preferências",
"general_settings": "Preferências padrão para o sistema.",
@ -1188,13 +1188,13 @@
"select_time_zone": "Selecione um fuso horário",
"select_date_format": "Selecionar um Formato de Data",
"select_financial_year": "Selecione o ano financeiro",
"recurring_invoice_status": "Status da fatura recorrente",
"create_status": "Criar Status",
"active": "Ativo",
"on_hold": "Em espera",
"update_status": "Atualizar Status",
"completed": "Concluído",
"company_currency_unchangeable": "Moeda da empresa não pode ser alterada"
"recurring_invoice_status": "Recurring Invoice Status",
"create_status": "Create Status",
"active": "Active",
"on_hold": "On Hold",
"update_status": "Update Status",
"completed": "Completed",
"company_currency_unchangeable": "Company currency cannot be changed"
},
"update_app": {
"title": "Atualizar Aplicativo",
@ -1217,10 +1217,10 @@
"finishing_update": "Acabando a Atualização",
"update_failed": "Atualização falhou",
"update_failed_text": "Desculpa! Sua atualização falhou no passo: {step}",
"update_warning": "Todos os arquivos de aplicativo e arquivos de modelo padrão serão substituídos quando você atualizar o aplicativo usando este utilitário. Faça um backup de seus templates e banco de dados antes de atualizar."
"update_warning": "All of the application files and default template files will be overwritten when you update the application using this utility. Please take a backup of your templates & database before updating."
},
"backup": {
"title": "Cópia de segurança | Cópias de segurança",
"title": "Backup | Backups",
"description": "O backup é um arquivo zip que contém todos os arquivos nas pastas que você especificou juntamente com um arquivo de backup de sua base de dados",
"new_backup": "Adicionar Novo Backup",
"create_backup": "Criar Backup",
@ -1248,7 +1248,7 @@
"created_at": "criado em",
"dropbox": "dropbox",
"name": "Nome",
"driver": "Motorista",
"driver": "Driver",
"disk_type": "Tipo",
"disk_name": "Nome do disco",
"new_disk": "Adicionar novo disco",
@ -1301,16 +1301,16 @@
"invalid_disk_credentials": "Credencial inválida para o disco selecionado"
},
"taxations": {
"add_billing_address": "Endereço de Cobrança do Cliente",
"add_shipping_address": "Endereço de Entrega do Cliente",
"add_company_address": "Insira o Endereço da Empresa",
"modal_description": "As informações abaixo são necessárias para obter o imposto sobre vendas.",
"add_address": "Adicionar endereço para buscar o imposto sobre vendas.",
"address_placeholder": "Exemplo: 123, Minha Rua",
"city_placeholder": "Exemplo: Los Angeles",
"state_placeholder": "Exemplo: CA",
"zip_placeholder": "Exemplo: 90024",
"invalid_address": "Forneça detalhes do endereço válido."
"add_billing_address": "Enter Billing Address",
"add_shipping_address": "Enter Shipping Address",
"add_company_address": "Enter Company Address",
"modal_description": "The information below is required in order to fetch sales tax.",
"add_address": "Add Address for fetching sales tax.",
"address_placeholder": "Example: 123, My Street",
"city_placeholder": "Example: Los Angeles",
"state_placeholder": "Example: CA",
"zip_placeholder": "Example: 90024",
"invalid_address": "Please provide valid address details."
}
},
"wizard": {
@ -1328,7 +1328,7 @@
"logo_preview": "Pré-visualizar Logotipo",
"preferences": "Preferências",
"preferences_desc": "Preferências padrão para o sistema.",
"currency_set_alert": "A moeda da empresa não pode ser alterada mais tarde.",
"currency_set_alert": "The company's currency cannot be changed later.",
"country": "País",
"state": "Estado",
"city": "Cidade",
@ -1372,7 +1372,7 @@
"app_domain": "Domínio do Aplicativo",
"verify_now": "Verificar Agora",
"success": "Domínio Verificado com Sucesso.",
"failed": "Falha na verificação de domínio. Digite um nome de domínio válido.",
"failed": "Domain verification failed. Please enter valid domain name.",
"verify_and_continue": "Verificar e Continuar"
},
"mail": {
@ -1425,7 +1425,7 @@
"not_yet": "Ainda não? Envie novamente",
"password_min_length": "A senha deve ter {count} caracteres",
"name_min_length": "O nome deve ter pelo menos {count} letras.",
"prefix_min_length": "O nome deve ter pelo menos {count} letras.",
"prefix_min_length": "Prefix must have at least {count} letters.",
"enter_valid_tax_rate": "Insira uma taxa de imposto válida",
"numbers_only": "Apenas Números.",
"characters_only": "Apenas Caracteres.",
@ -1440,7 +1440,7 @@
"price_minvalue": "O preço deve ser maior que 0.",
"amount_maxlength": "Valor não deve ter mais de 20 dígitos.",
"amount_minvalue": "O valor deve ser maior que 0.",
"discount_maxlength": "Desconto não deve ser maior que o máximo de desconto",
"discount_maxlength": "Discount should not be greater than max discount",
"description_maxlength": "A descrição não deve ter mais que 255 caracteres.",
"subject_maxlength": "O assunto não deve ter mais que 100 caracteres.",
"message_maxlength": "A mensagem não deve ter mais que 255 caracteres.",
@ -1451,41 +1451,41 @@
"prefix_maxlength": "O prefixo não deve ter mais que 5 caracteres.",
"something_went_wrong": "algo deu errado",
"number_length_minvalue": "O valor deve ser maior que 0",
"at_least_one_ability": "Você deve selecionar ao menos uma permissão.",
"valid_driver_key": "Por favor, insira uma chave válida de {driver}.",
"valid_exchange_rate": "Por favor digite a taxa de câmbio.",
"company_name_not_same": "O nome da empresa deve corresponder com o nome fornecido."
"at_least_one_ability": "Please select atleast one Permission.",
"valid_driver_key": "Please enter a valid {driver} key.",
"valid_exchange_rate": "Please enter a valid exchange rate.",
"company_name_not_same": "Company name must match with given name."
},
"errors": {
"starter_plan": "Este recurso está disponível no plano de Starter!",
"invalid_provider_key": "Por favor, insira uma chave de API do provedor válido.",
"estimate_number_used": "O número de pagamento já está em uso.",
"invoice_number_used": "O número da fatura já está em uso.",
"payment_attached": "Uma das faturas selecionadas já possui um pagamento anexado. Certifique-se de excluir os pagamentos anexados primeiro, para continuar com a exclusão.",
"payment_number_used": "O número de pagamento já está em uso.",
"name_already_taken": "O nome já está em uso.",
"receipt_does_not_exist": "O recibo não existe.",
"customer_cannot_be_changed_after_payment_is_added": "O cliente não pode ser alterado após o pagamento ser adicionado",
"invalid_credentials": "Credenciais inválidas",
"not_allowed": "Não permitido",
"login_invalid_credentials": "Credenciais não correspondem aos nossos registros.",
"enter_valid_cron_format": "Por favor, insira um formato de URL válida",
"email_could_not_be_sent": "Não foi possível enviar o e-mail para este endereço de e-mail.",
"invalid_address": "Por favor, insira um endereço de e-mail válido.",
"invalid_key": "Favor inserir uma chave válida.",
"invalid_state": "Por favor, insira um estado válido.",
"invalid_city": "Por favor, insira uma cidade válida.",
"invalid_postal_code": "Por favor, insira um CEP válido.",
"invalid_format": "Por favor, insira o formato de texto de consulta válido.",
"api_error": "O servidor não está respondendo",
"feature_not_enabled": "Recurso não ativado.",
"request_limit_met": "Limite de solicitações excedido",
"address_incomplete": "Endereço Incompleto"
"starter_plan": "This feature is available on Starter plan and onwards!",
"invalid_provider_key": "Please Enter Valid Provider API Key.",
"estimate_number_used": "The estimate number has already been taken.",
"invoice_number_used": "The invoice number has already been taken.",
"payment_attached": "This invoice already has a payment attached to it. Make sure to delete the attached payments first in order to go ahead with the removal.",
"payment_number_used": "The payment number has already been taken.",
"name_already_taken": "The name has already been taken.",
"receipt_does_not_exist": "Receipt does not exist.",
"customer_cannot_be_changed_after_payment_is_added": "Customer cannot be change after payment is added",
"invalid_credentials": "Invalid Credentials.",
"not_allowed": "Not Allowed",
"login_invalid_credentials": "These credentials do not match our records.",
"enter_valid_cron_format": "Please enter a valid cron format",
"email_could_not_be_sent": "Email could not be sent to this email address.",
"invalid_address": "Please enter a valid address.",
"invalid_key": "Please enter valid key.",
"invalid_state": "Please enter a valid state.",
"invalid_city": "Please enter a valid city.",
"invalid_postal_code": "Please enter a valid zip.",
"invalid_format": "Please enter valid query string format.",
"api_error": "Server not responding.",
"feature_not_enabled": "Feature not enabled.",
"request_limit_met": "Api request limit exceeded.",
"address_incomplete": "Incomplete Address"
},
"pdf_estimate_label": "Orçamento",
"pdf_estimate_number": "Numero do Orçamento",
"pdf_estimate_date": "Data do Orçamento",
"pdf_estimate_expire_date": "Validade",
"pdf_estimate_expire_date": "Data de expiração",
"pdf_invoice_label": "Fatura",
"pdf_invoice_number": "Número da fatura",
"pdf_invoice_date": "Data da Fatura",
@ -1522,5 +1522,5 @@
"pdf_bill_to": "Cobrar a,",
"pdf_ship_to": "Envie a,",
"pdf_received_from": "Remetente:",
"pdf_tax_label": "Imposto"
"pdf_tax_label": "Tax"
}

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Estimate",
"pdf_estimate_number": "Estimate Number",
"pdf_estimate_date": "Estimate Date",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Expiry date",
"pdf_invoice_label": "Invoice",
"pdf_invoice_number": "Invoice Number",
"pdf_invoice_date": "Invoice Date",

File diff suppressed because it is too large Load Diff

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Cenový odhad",
"pdf_estimate_number": "Číslo cenového odhadu",
"pdf_estimate_date": "Dátum cenového odhadu",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Platnosť cenového odhadu",
"pdf_invoice_label": "Faktúra",
"pdf_invoice_number": "Číslo faktúry",
"pdf_invoice_date": "Dátum vystavenia",

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
"settings": "Podešavanja",
"logout": "Odjavi se",
"users": "Korisnici",
"modules": "Moduli"
"modules": "Modules"
},
"general": {
"add_company": "Dodaj kompaniju",
@ -30,8 +30,8 @@
"from": "Pošiljalac",
"to": "Primalac",
"ok": "Ok",
"yes": "Da",
"no": "Ne",
"yes": "Yes",
"no": "No",
"sort_by": "Rasporedi Po",
"ascending": "Rastuće",
"descending": "Opadajuće",
@ -39,7 +39,7 @@
"body": "Telo",
"message": "Poruka",
"send": "Pošalji",
"preview": "Pregled",
"preview": "Preview",
"go_back": "Idi nazad",
"back_to_login": "Nazad na prijavu?",
"home": "Početna",
@ -95,9 +95,9 @@
"copied_pdf_url_clipboard": "Link do PDF fajla kopiran!",
"copied_url_clipboard": "Copied url to clipboard!",
"docs": "Docs",
"do_you_wish_to_continue": "Da li želite nastaviti?",
"note": "Bilješka",
"pay_invoice": "Plati račun",
"do_you_wish_to_continue": "Do you wish to continue?",
"note": "Note",
"pay_invoice": "Pay Invoice",
"login_successfully": "Logged in successfully!",
"logged_out_successfully": "Logged out successfully",
"mark_as_default": "Mark as default"
@ -318,10 +318,10 @@
},
"accepted": "Prihvaćeno",
"rejected": "Odbijeno",
"expired": "Istekao",
"expired": "Expired",
"sent": "Poslato",
"draft": "U izradi",
"viewed": "Pregledano",
"viewed": "Viewed",
"declined": "Odbijeno",
"new_estimate": "Nova Profaktura",
"add_new_estimate": "Dodaj novu Profakturu",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Profaktura",
"pdf_estimate_number": "Broj Profakture",
"pdf_estimate_date": "Datum Profakture",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Datum isteka Profakture",
"pdf_invoice_label": "Faktura",
"pdf_invoice_number": "Broj Fakture",
"pdf_invoice_date": "Datum Fakture",

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Kostnadsförslag",
"pdf_estimate_number": "Kostnadsförslagsnummer",
"pdf_estimate_date": "Kostnadsförslagsdatum",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Utgångsdatum",
"pdf_invoice_label": "Faktura",
"pdf_invoice_number": "Fakturanummer",
"pdf_invoice_date": "Fakturadatum",

File diff suppressed because it is too large Load Diff

View File

@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Estimate",
"pdf_estimate_number": "Estimate Number",
"pdf_estimate_date": "Estimate Date",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Expiry date",
"pdf_invoice_label": "Invoice",
"pdf_invoice_number": "Invoice Number",
"pdf_invoice_date": "Invoice Date",

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
"settings": "Cài đặt",
"logout": "Đăng xuất",
"users": "Người dùng",
"modules": "Các Mô-Đun"
"modules": "Modules"
},
"general": {
"add_company": "Thêm công ty",
@ -93,7 +93,7 @@
"no_note_found": "Không tìm thấy ghi chú",
"insert_note": "Chèn ghi chú",
"copied_pdf_url_clipboard": "Đã sao chép url PDF vào khay nhớ tạm!",
"copied_url_clipboard": "Đã sao chép url vào khay nhớ tạm!",
"copied_url_clipboard": "Copied url to clipboard!",
"docs": "Tài liệu",
"do_you_wish_to_continue": "Bạn có muốn tiếp tục không?",
"note": "Ghi chú",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "Ước tính",
"pdf_estimate_number": "Số ước tính",
"pdf_estimate_date": "Ngày ước tính",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "Ngày hết hạn",
"pdf_invoice_label": "Hóa đơn",
"pdf_invoice_number": "Số hóa đơn",
"pdf_invoice_date": "Ngày lập hóa đơn",

View File

@ -93,14 +93,14 @@
"no_note_found": "沒有找到備註",
"insert_note": "插入備註",
"copied_pdf_url_clipboard": "複製PDF位址到剪貼簿!",
"copied_url_clipboard": "將網址複製到剪貼簿!",
"copied_url_clipboard": "Copied url to clipboard!",
"docs": "文檔",
"do_you_wish_to_continue": "你確定要繼續?",
"note": "備註",
"pay_invoice": "支付發票",
"login_successfully": "已成功登入!",
"logged_out_successfully": "已成功登出",
"mark_as_default": "標記為預設值"
"pay_invoice": "Pay Invoice",
"login_successfully": "Logged in successfully!",
"logged_out_successfully": "Logged out successfully",
"mark_as_default": "Mark as default"
},
"dashboard": {
"select_year": "選擇年份",
@ -109,7 +109,7 @@
"customers": "客户",
"invoices": "發票",
"estimates": "報價",
"payments": "付款"
"payments": "Payments"
},
"chart_info": {
"total_sales": "銷售",
@ -208,10 +208,10 @@
"new_customer": "新客戶",
"edit_customer": "編輯客戶",
"basic_info": "基本資料",
"portal_access": "門戶訪問",
"portal_access_text": "您想允許此客戶登入客戶門戶嗎?",
"portal_access_url": "客戶門戶登入URL",
"portal_access_url_help": "請將上述給定的URL複製並轉發給您的客戶以提供訪問許可權。",
"portal_access": "Portal Access",
"portal_access_text": "Would you like to allow this customer to login to the Customer Portal?",
"portal_access_url": "Customer Portal Login URL",
"portal_access_url_help": "Please copy & forward the above given URL to your customer for providing access.",
"billing_address": "帳單地址",
"shipping_address": "送貨地址",
"copy_billing_address": "由帳單複製",
@ -231,7 +231,7 @@
"confirm_delete": "你將不能夠還原此客戶, 以及此客戶相關的發票, 報價及付款. | 你將不能夠還原此客戶, 以及此客戶相關的發票, 報價及付款.",
"created_message": "成功新增客戶",
"updated_message": "成功更新客戶",
"address_updated_message": "地址資訊已成功更新",
"address_updated_message": "Address Information Updated succesfully",
"deleted_message": "成功刪除客戶 | 成功刪除客戶",
"edit_currency_not_allowed": "交易一旦創建後就不能改變貨幣!"
},
@ -265,8 +265,8 @@
},
"estimates": {
"title": "報價",
"accept_estimate": "接受估價",
"reject_estimate": "拒絕估算",
"accept_estimate": "Accept Estimate",
"reject_estimate": "Reject Estimate",
"estimate": "報價 | 報價",
"estimates_list": "報價列表",
"days": "{days} 天",
@ -318,10 +318,10 @@
},
"accepted": "已接受",
"rejected": "已拒絕",
"expired": "已過期",
"expired": "Expired",
"sent": "傳送",
"draft": "草稿",
"viewed": "已檢視",
"viewed": "Viewed",
"declined": "拒絕",
"new_estimate": "新報價",
"add_new_estimate": "新增報價",
@ -355,14 +355,14 @@
"select_an_item": "輸入或點擊去選擇商品",
"type_item_description": "商品詳情(可選)"
},
"mark_as_default_estimate_template_description": "如果啟用,所選模板將自動選擇新的估算。"
"mark_as_default_estimate_template_description": "If enabled, the selected template will be automatically selected for new estimates."
},
"invoices": {
"title": "發票",
"download": "下載",
"pay_invoice": "支付發票",
"download": "Download",
"pay_invoice": "Pay Invoice",
"invoices_list": "發票列表",
"invoice_information": "發票資訊",
"invoice_information": "Invoice Information",
"days": "{days} 天",
"months": "{months} 月",
"years": "{years} 年",
@ -447,7 +447,7 @@
"marked_as_sent_message": "發票已標示為成功傳送",
"something_went_wrong": "出現錯誤",
"invalid_due_amount_message": "發票總額不能少於支付總額. 請更新發票或刪除相關支付再繼續.",
"mark_as_default_invoice_template_description": "如果啟用,所選模板將自動選擇新發票"
"mark_as_default_invoice_template_description": "If enabled, the selected template will be automatically selected for new invoices."
},
"recurring_invoices": {
"title": "定期發票",
@ -464,11 +464,11 @@
"completed": "已完成",
"customer": "客戶",
"paid_status": "付款狀態",
"ref_no": "參考號碼",
"number": "",
"amount_due": "到期金額",
"partially_paid": "部分支付",
"total": "總計",
"ref_no": "REF NO.",
"number": "NUMBER",
"amount_due": "AMOUNT DUE",
"partially_paid": "Partially Paid",
"total": "Total",
"discount": "Discount",
"sub_total": "Sub Total",
"invoice": "Recurring Invoice | Recurring Invoices",
@ -504,16 +504,16 @@
"invoice_mark_as_sent": "This recurring invoice will be marked as sent",
"confirm_send": "This recurring invoice will be sent via email to the customer",
"starts_at": "Start Date",
"due_date": "發票到期日期",
"record_payment": "紀錄付款",
"add_new_invoice": "添加定期發票",
"update_expense": "更新支出",
"edit_invoice": "編輯定期發票",
"new_invoice": "添加定期發票",
"send_automatically": "自動發送",
"send_automatically_desc": "如果您希望在建立發票時自動將發票發送給客戶,請啟用此選項。",
"save_invoice": "保存定期發票",
"update_invoice": "更新定期發票",
"due_date": "Invoice Due Date",
"record_payment": "Record Payment",
"add_new_invoice": "Add New Recurring Invoice",
"update_expense": "Update Expense",
"edit_invoice": "Edit Recurring Invoice",
"new_invoice": "New Recurring Invoice",
"send_automatically": "Send Automatically",
"send_automatically_desc": "Enable this, if you would like to send the invoice automatically to the customer when its created.",
"save_invoice": "Save Recurring Invoice",
"update_invoice": "Update Recurring Invoice",
"add_new_tax": "Add New Tax",
"no_invoices": "No Recurring Invoices yet!",
"mark_as_rejected": "Mark as rejected",
@ -1485,7 +1485,7 @@
"pdf_estimate_label": "報價",
"pdf_estimate_number": "報價單號",
"pdf_estimate_date": "報價日期",
"pdf_estimate_expire_date": "Expiry Date",
"pdf_estimate_expire_date": "有效日期",
"pdf_invoice_label": "發票",
"pdf_invoice_number": "發票號碼",
"pdf_invoice_date": "發票日期",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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