Compare commits

..

1 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
341bcbea7d feat: database backup script 2024-04-28 18:04:56 +02:00
3544 changed files with 17791 additions and 227115 deletions

View File

@@ -123,51 +123,6 @@
"contributions": [
"code"
]
},
{
"login": "ccantrell72",
"name": "Chris Cantrell",
"avatar_url": "https://avatars.githubusercontent.com/u/104120598?v=4",
"profile": "http://www.pivoten.com",
"contributions": [
"bug"
]
},
{
"login": "oleynikd",
"name": "Denis",
"avatar_url": "https://avatars.githubusercontent.com/u/3976868?v=4",
"profile": "https://github.com/oleynikd",
"contributions": [
"bug"
]
},
{
"login": "mittalsam98",
"name": "Sachin Mittal",
"avatar_url": "https://avatars.githubusercontent.com/u/42431274?v=4",
"profile": "https://myself.vercel.app/",
"contributions": [
"bug"
]
},
{
"login": "Champetaman",
"name": "Camilo Oviedo",
"avatar_url": "https://avatars.githubusercontent.com/u/64604272?v=4",
"profile": "https://www.camilooviedo.com/",
"contributions": [
"code"
]
},
{
"login": "nklmantey",
"name": "Mantey",
"avatar_url": "https://avatars.githubusercontent.com/u/90279429?v=4",
"profile": "https://nklmantey.com/",
"contributions": [
"bug"
]
}
],
"contributorsPerLine": 7,

View File

@@ -1,6 +1,3 @@
# App
APP_JWT_SECRET=123123
# Mail
MAIL_HOST=
MAIL_USERNAME=
@@ -51,9 +48,6 @@ SIGNUP_DISABLED=false
SIGNUP_ALLOWED_DOMAINS=
SIGNUP_ALLOWED_EMAILS=
# Sign-up Email Confirmation
SIGNUP_EMAIL_CONFIRMATION=false
# API rate limit (points,duration,block duration).
API_RATE_LIMIT=120,60,600
@@ -78,28 +72,31 @@ PLAID_ENV=sandbox
# Your Plaid keys, which can be found in the Plaid Dashboard.
# https://dashboard.plaid.com/account/keys
PLAID_CLIENT_ID=
PLAID_SECRET=
PLAID_SECRET_DEVELOPMENT=
PLAID_SECRET_SANDBOX=
PLAID_LINK_WEBHOOK=
# (Optional) Redirect URI settings section
# Only required for OAuth redirect URI testing (not common on desktop):
# Sandbox Mode:
# Set the PLAID_SANDBOX_REDIRECT_URI below to 'http://localhost:3001/oauth-link'.
# The OAuth redirect flow requires an endpoint on the developer's website
# that the bank website should redirect to. You will also need to configure
# this redirect URI for your client ID through the Plaid developer dashboard
# at https://dashboard.plaid.com/team/api.
# Development mode:
# When running in development mode, you must use an https:// url.
# You will need to configure this https:// redirect URI in the Plaid developer dashboard.
# Instructions to create a self-signed certificate for localhost can be found at
# https://github.com/plaid/pattern/blob/master/README.md#testing-oauth.
# If your system is not set up to run localhost with https://, you will be unable to test
# the OAuth in development and should leave the PLAID_DEVELOPMENT_REDIRECT_URI blank.
PLAID_SANDBOX_REDIRECT_URI=
PLAID_DEVELOPMENT_REDIRECT_URI=
# https://docs.lemonsqueezy.com/guides/developer-guide/getting-started#create-an-api-key
LEMONSQUEEZY_API_KEY=
LEMONSQUEEZY_STORE_ID=
LEMONSQUEEZY_WEBHOOK_SECRET=
# S3 documents and attachments
S3_REGION=US
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_ENDPOINT=
S3_BUCKET=
# PostHog
POSTHOG_API_KEY=
POSTHOG_HOST=
# Stripe Payment
STRIPE_PAYMENT_SECRET_KEY=
STRIPE_PAYMENT_PUBLISHABLE_KEY=
STRIPE_PAYMENT_CLIENT_ID=
STRIPE_PAYMENT_WEBHOOKS_SECRET=
STRIPE_PAYMENT_REDIRECT_URL=

View File

@@ -6,13 +6,18 @@ on:
workflow_dispatch:
env:
WEBAPP_IMAGE_NAME: bigcapitalhq/webapp
SERVER_IMAGE_NAME: bigcapitalhq/server
REGISTRY: ghcr.io
WEBAPP_IMAGE_NAME: bigcapital/bigcapital-webapp
SERVER_IMAGE_NAME: bigcapital/bigcapital-server
jobs:
build-publish-webapp:
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
name: Build and deploy webapp container
runs-on: ubuntu-latest
environment: production
@@ -25,6 +30,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -32,26 +40,27 @@ jobs:
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GH_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.WEBAPP_IMAGE_NAME }}
images: ${{ env.REGISTRY }}/${{ env.WEBAPP_IMAGE_NAME }}
# Builds and push the Docker image.
- name: Build and push Docker image
uses: docker/build-push-action@v5
id: build
with:
context: ./
context: .
file: ./packages/webapp/Dockerfile
platforms: linux/amd64,linux/arm64
platforms: ${{ matrix.platform }}
push: true
tags: ghcr.io/bigcapitalhq/webapp:latest
labels: ${{ steps.meta.outputs.labels }}
tags: bigcapitalhq/webapp:latest, bigcapitalhq/webapp:${{github.ref_name}}
- name: Export digest
run: |
@@ -62,7 +71,7 @@ jobs:
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-webapp
name: digests-main-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
@@ -84,6 +93,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -91,8 +103,9 @@ jobs:
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GH_TOKEN }}
# Builds and push the Docker image.
- name: Build and push Docker image
@@ -101,9 +114,9 @@ jobs:
with:
context: ./
file: ./packages/server/Dockerfile
platforms: linux/amd64,linux/arm64
platforms: ${{ matrix.platform }}
push: true
tags: bigcapitalhq/server:latest, bigcapitalhq/server:${{github.ref_name}}
tags: ghcr.io/bigcapitalhq/server:latest
labels: ${{ steps.meta.outputs.labels }}
- name: Export digest
@@ -115,13 +128,13 @@ jobs:
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-server
name: digests-main-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
# Send notification to Slack channel.
- name: Slack Notification built and published server container successfully.
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

View File

@@ -1,127 +0,0 @@
# This workflow will build a docker container, publish it to Github Registry.
name: Build and Deploy Develop Docker Container
on:
push:
branches:
- develop
env:
WEBAPP_IMAGE_NAME: bigcapitalhq/webapp
SERVER_IMAGE_NAME: bigcapitalhq/server
jobs:
build-publish-webapp:
strategy:
fail-fast: false
name: Build and deploy webapp container
runs-on: ubuntu-latest
environment: production
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Login to Container registry.
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.WEBAPP_IMAGE_NAME }}
# Builds and push the Docker image.
- name: Build and push Docker image
uses: docker/build-push-action@v5
id: build
with:
context: ./
file: ./packages/webapp/Dockerfile
platforms: linux/amd64
push: true
labels: ${{ steps.meta.outputs.labels }}
tags: bigcapitalhq/webapp:develop
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-webapp
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
# Send notification to Slack channel.
- name: Slack Notification built and published webapp container successfully.
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
build-publish-server:
name: Build and deploy server container
runs-on: ubuntu-latest
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Login to Container registry.
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# Builds and push the Docker image.
- name: Build and push Docker image
uses: docker/build-push-action@v5
id: build
with:
context: ./
file: ./packages/server/Dockerfile
platforms: linux/amd64
push: true
tags: bigcapitalhq/server:develop
labels: ${{ steps.meta.outputs.labels }}
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-server
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
# Send notification to Slack channel.
- name: Slack Notification built and published server container successfully.
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

3
.gitignore vendored
View File

@@ -6,5 +6,4 @@ node_modules/
# Production env file
.env
test-results/
.qodo
test-results/

View File

@@ -2,341 +2,6 @@
All notable changes to Bigcapital server-side will be in this file.
# [0.22.0]
* feat: estimate, receipt, credit note mail preview by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/757
* feat: Add discount to transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/758
* fix: update financial forms to use new formatted amount utilities and… by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/760
* fix: total lines style by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/761
* fix: discount & adjustment sale transactions bugs by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/762
* fix: discount transactions GL entries by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/763
# [0.21.2]
* hotbug: upload attachments by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/755
# [0.21.1]
* fix: download invoice document on payment page by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/750
* fix: attach branding template attrs to payment page by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/751
* fix: make manual entries adjust decimal credit/debit amounts by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/754
* feat: allow quantity of entries accept decimal value by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/753
# [0.21.0]
* fix: Credit and debit totals not balancing when decimal values are used by @nklmantey in https://github.com/bigcapitalhq/bigcapital/pull/722
* docs: add nklmantey as a contributor for bug by @allcontributors in https://github.com/bigcapitalhq/bigcapital/pull/725
* feat: track more services events by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/721
* feat: Invoice mail receipt preview by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/723
* fix: change the send mail button on invoice drawer by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/730
* refactor: notification mail services by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/731
* fix: attach payment link in sending invoice mail receipt by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/732
* fix: send invoice drawer layout by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/733
* fix: hook up cc and bcc fields to mail sender by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/734
* fix: company logo does not show up in mail receipt preview by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/736
* fix: change default invoice mail message by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/737
* fix: typing invoice send mail fields by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/738
* fix: clean up ivnoice mail receipt preview component by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/739
* feat: add shared package to pdf templates to render in the server and… by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/735
* feat: getting invoice preview on send mail view by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/740
* fix: style SSR invoice paper template by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/741
* fix: send invoice receipt addresses by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/742
* fix: due invoice server invoice by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/744
* fix: `BIG-265` forgot password text by @ibutiti in https://github.com/bigcapitalhq/bigcapital/pull/745
* Crims on sv translation by @Crims-on in https://github.com/bigcapitalhq/bigcapital/pull/671
* feat: Added Spanish language to the App 🇪🇸 by @angelosorno in https://github.com/bigcapitalhq/bigcapital/pull/530
* fix: mail services by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/746
* fix: company logo of the template by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/747
* fix: monorepo dependencies scope by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/748
# [0.20.6]
* fix: Import category column of item resource by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/710
* fix: Parse the uppercase values in importing by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/711
* chore: Move i18nApply localization to the account transformer by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/713
* fix: Sync Plaid credit card account type by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/714
* fix: Sync account normal of cashflow GL entries by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/715
* feat: Add quantity column to pdf templates by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/716
* feat: Pre-line invoice statements by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/717
* feat: Invoice number in downloaded pdf document by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/718
* feat: Track events of pdf documents views by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/719
* fix: Customer note does not appear in pdf document by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/720
# [0.20.5]
* fix: Disable tabs of the pdf customization if the first field not filed up by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/701
* fix: Invoice form layout by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/705
* refactor: Invoice, estimate, receipt, credit note and payment received date input fields by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/707
* feat: Add customize templates button to edit forms by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/708
* feat: Track account, invoice and item viewed events by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/709
# [0.20.4]
* fix: Delete company logo from the PDF template by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/699
* fix: Set max width/height to company logo of pdf templates by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/700
# [0.20.3]
* feat: Assign default PDF template automatically by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/687
* fix: pdf template addresses controlling by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/688
* fix: Remove empty lines from address formats by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/690
* fix: Pdf templates layout by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/691
* feat: Download invoice pdf of the payment link by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/689
* fix: Display country name by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/693
* feat: Add shared packages to Docker container by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/694
# [0.20.2]
* feat: Assign default PDF template automatically by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/687
* fix: pdf template addresses controlling by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/688
* fix: Remove empty lines from address formats by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/690
* fix: Pdf templates layout by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/691
* feat: Download invoice pdf of the payment link by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/689
* fix: Display country name by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/693
* feat: Add shared packages to Docker container by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/694
# [0.20.1]
* fix: Getting uploaded object uri by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/684
# [0.20.0]
* feat: Customize pdf templates by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/667
* feat: Onboard accounts to Stripe Connect by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/668
* feat: Upload company logo to invoice templates by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/670
* fix: Invoice pdf customize by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/672
* fix: Invoice customize bugs by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/673
* feat: Clean up payment links endpoints by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/674
* feat: Hook up company logo to server-side pdf templates by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/675
* feat: Company branding preferences by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/677
* feat: Pdf templates customer/company addresses by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/678
* fix: Listen to Stripe session completed event by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/679
* feat: Track pdf templates Posthog events by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/680
* fix: Branding customize content by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/681
* feat: Listen to Stripe integration events by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/682
* feat: Hook up customer/company address to invoice preview of payment page by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/683
# [0.19.17]
* fix: Un-categorize bank transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/663
# [0.19.16]
* feat: Tracking more Posthog events by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/653
* fix: Expense cannot accept credit card as payment account by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/654
* fix: Suspense the lazy loaded components in banking pages by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/657
* feat: Add help dropdown menu by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/656
* feat: Bank pages layout breaking by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/658
* feat: Datatable UI improvements by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/655
* fix: Array cast of recognize function rule ids by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/660
* fix: Payment made filling the form full amount field by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/661
* feat: Tabular number of all money columns by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/659
* refactor: The expense G/L writer by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/662
## [0.19.15] -
* fix: Bank transactions infinity scrolling by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/648
* feat: Integrate multiple branches and warehouses to resource importing by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/645
* fix: Integrate multiple branches with expense resource by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/649
* feat: Cover more tracking events. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/650
* feat: Track banking service events by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/651
## [0.19.14]
* fix: Import bugs by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/643
* fix: Set default index to transaction entries by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/644
* feat(server): Events tracking using Posthog by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/646
## [0.19.13]
* fix: Subscription middleware by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/624
* fix: Getting the sheet columns in import sheet by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/641
## [0.19.12]
* fix: Typo one-click demo page by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/640
## [0.19.11]
* fix: Avoid running the cost job in import preview by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/635
* fix: Debounce scheduling calculating items cost by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/634
* fix: Expand the resources export page size limitation by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/636
* feat: Optimize loading perf. by splitting big chunks and lazy loading them by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/632
* fix: Use standard ISO 8601 format for exported data by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/638
* fix: Add customer type to customers resource by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/639
## [0.19.10]
* fix: Add subscription plans offer text by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/629
## [0.19.9]
* fix: Make webapp package env variables dynamic by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/628
## [v0.19.8]
* fix: Cannot import items income and cost accounts by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/617
* fix: Some bank account details hidden by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/618
* feat(ee): One-click demo account by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/616
* feat: change banking service language by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/619
* feat(banking): Filter uncategorized bank transactions by date by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/590
* Fix: Syntax error caused error by @wolone in https://github.com/bigcapitalhq/bigcapital/pull/622
* fix: Listen to payment webhooks by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/623
* fix: Add prefix J-00001 to manual journals increments by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/625
* fix: Disable sms service until Twilo integration by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/626
* fix: Style tweaks in onboarding page by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/627
## [0.19.5] - 18-08-2024
* fix: Allow multi-lines to statements transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/594
* feat: Add amount comparators to amount bank rule field by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/595
* fix: Transaction type and description do not show in general ledger. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/596
* fix: Refresh accounts and account transactions. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/597
* fix: Typo payments made by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/598
* fix: Typo categories list by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/600
* fix: Autofill the quick created customer/vendor by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/601
* fix: Remove views tabs from receipts list by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/602
* fix: Typo payment receive messages by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/599
* fix: Enhance Dropzone visual of accept and reject modes by @Champetaman in https://github.com/bigcapitalhq/bigcapital/pull/603
* fix: Matching bank transactions should create associate payment transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/606
* fix: Change Dropzone title and subtitle by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/607
* fix: Inconsistance page size of paginated data tables by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/604
* fix: Database connection lost error by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/611
* fix: Language typos by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/613
* Fix: Correctly display Date, Published At, and Created At in ExpenseDrawerHeader by @Champetaman in https://github.com/bigcapitalhq/bigcapital/pull/612
* fix: Delete bank account with uncategorized transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/614
* feat: activate/inactivate account from drawer details by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/615
## [v0.19.4]
* feat: Import and export tax rates by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/591
* feat: Un-categorize bank transactions in bulk by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/587
* feat: Pending bank transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/589
* fix: Update `dev` Script in `package.json` to Use `cross-env` by @Champetaman in https://github.com/bigcapitalhq/bigcapital/pull/588
* fix: Should not load branches on reconcile matching form if the branches not enabled by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/592
* fix: Rounding the total amount the pending and matched transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/593
## [v0.18.0] - 10-08-2024
* feat: Bank rules for automated categorization by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/511
* feat: Categorize & match bank transaction by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/511
* feat: Reconcile match transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/522
* fix: Issues in matching transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/523
* fix: Cashflow transactions types by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/524
## [v0.17.5] - 17-06-2024
* fix: Balance sheet and P/L nested accounts by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/501
* fix: add space between buttons on floating actions bar by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/508
* feat: Migrating to Envoy proxy instead of Nginx by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/509
* fix: Disable email confirmation does not work with invited users by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/497
* feat: Setting up the date format in the whole system dates by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/506
## [0.17.0] - 04-06-2024
### New
* feat: Upload and attach documents by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/461
* feat: Export resource tables to pdf by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/460
* feat: Build and deploy develop Docker container by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/476
* feat: Internal docker virtual network by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/478
### Fixes
* fix: Skip send confirmation email if disabled by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/459
* fix: Lemon Squeezy redirect to base url by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/479
* fix: Organize Plaid env variables for development and sandbox envs by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/480
* fix: Plaid syncs deposit imports as withdrawals by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/481
* fix: Validate the s3 configures exist by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/482
* fix: Run migrations only for initialized tenants by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/484
## [0.16.16] -
* feat: handle http exceptions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/456
* feat: add the missing Newrelic env vars to docker-compose.prod file by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/457
* fix: add the signup email confirmation env var by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/458
## [0.16.14] -
* fix: Typo in setup wizard by @ccantrell72 in https://github.com/bigcapitalhq/bigcapital/pull/440
* fix: Showing the real mail address on email confirmation view by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/445
* fix: Auto-increment setting parsing by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/453
## [0.16.12] -
* feat: Create a manifest list for `webapp` Docker image and push it to DockerHub. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/436
* feat: Combine arm64 and amd64 in one Github action runner by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/437
## [0.16.11] - 06-05-2024
### improvements
* feat: Export resource data to csv, xlsx by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/430
* feat: User email verification after signing-up. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/426
### Fixes
* feat(repo): upgrade to latest lerna v8 and pnpm v9 by @benpsnyder in https://github.com/bigcapitalhq/bigcapital/pull/414
* feat: Update Docker Build-Push Action and Add ARM64 Support by @cloudsbird in https://github.com/bigcapitalhq/bigcapital/pull/412
* feat: Pushing docker containers by version tag by @cloudsbird in https://github.com/bigcapitalhq/bigcapital/pull/421
## [0.16.10]
* fix: Running migration Docker container on Windows by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/432
## [0.16.9]
* feat: New Relic for tracking by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/429
## [0.16.8]
* feat: Ability to enable/disable the bank connect feature by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/423
## [0.16.6]
* hotfix: fix the subscription plan when subscribe on cloud by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/422
## [0.16.5]
IMPORTANT: If you upgraded to the v0.16 recently you should upgrade to v0.16.4 as soon as possible, because there're some breaking changes affected the sign-in and some users reported couldn't sign-in.
* feat: Seed free subscription to tenants that have no subscription. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/410
## [0.16.3]
* feat: Integrate Lemon Squeezy payment by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/402
* feat: optimize the onboarding subscription experience. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/404
* feat: subscription page content by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/405
* feat: auto subscribe to free plan once signup on community version. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/406
* chore: add default value to env variable by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/407
* fix: absolute storage imports path. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/408
## [0.16.0]
* feat: add convert to invoice button on estimate drawer toolbar by @ANasouf in https://github.com/bigcapitalhq/bigcapital/pull/361
* feat(webapp): add mark as delivered to action bar of invoice details … by @ANasouf in https://github.com/bigcapitalhq/bigcapital/pull/360
* feat(webapp): Dialog to choose the bank service provider by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/378
* feat: Categorize the bank synced transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/377
* feat: uncategorize the cashflow transaction by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/381
* Import resources from csv/xlsx by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/382
* feat(webapp): import resource UI by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/386
* fix: import resources improvements by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/388
* feat: add sample sheet to accounts and bank transactions by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/389
* fix: show the unique row value in the import preview by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/392
* feat: advanced parser for numeric and boolean import values by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/394
* feat: validate the given imported sheet whether is empty by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/395
* feat: linking relation with id in importing by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/393
* feat: Aggregate rows import by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/396
* feat: clean up the imported temp files by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/400
* feat: add hints to import fields by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/401
## [0.15.0]
* feat: Printing financial reports by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/363
* feat: Convert invoice status after sending mail notification by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/332
* feat: Bigcapital <> Plaid Integration by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/346
* fix: Broken transactions by vendor report by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/369
* fix: Optimize the print style some financial reports by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/370
## [0.14.0] - 30-01-2024
* feat: purchases by items exporting by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/327

View File

@@ -1,6 +1,6 @@
<p align="center">
<p align="center">
<a href="https://bigcapital.app" target="_blank">
<a href="https://bigcapital.ly" target="_blank">
<img src="https://raw.githubusercontent.com/abouolia/blog/main/public/bigcapital.svg" alt="Bigcapital" width="280" height="75">
</a>
</p>
@@ -12,9 +12,6 @@
<a href="https://github.com/bigcapitalhq/bigcapital/commits/develop">
<img src="https://img.shields.io/github/commit-activity/m/bigcapitalhq/bigcapital/develop" />
</a>
<a href="https://hub.docker.com/u/bigcapitalhq">
<img src="https://img.shields.io/docker/pulls/bigcapitalhq/webapp" />
</a>
<a href="https://discord.com/invite/c8nPBJafeb">
<img src="https://img.shields.io/discord/1066514716752625725?label=Discord" alt="" />
</a>
@@ -30,7 +27,7 @@
</p>
<p align="center">
<a href="https://my.bigcapital.app">Bigcapital Cloud</a>
<a href="https://app.bigcapital.ly">Bigcapital Cloud</a>
</p>
</p>
@@ -54,7 +51,7 @@ Bigcapital is available open-source under AGPL license. You can host it on your
### Docker
To get started with self-hosted with Docker and Docker Compose, take a look at the [Docker guide](https://docs.bigcapital.app/deployment/docker).
To get started with self-hosted with Docker and Docker Compose, take a look at the [Docker guide](https://docs.bigcapital.ly/deployment/docker).
## Development
@@ -77,7 +74,7 @@ You can integrate Bigcapital API with your system to organize your transactions
# Resources
- [Documentation](https://docs.bigcapital.app/) - Learn how to use.
- [Documentation](https://docs.bigcapital.ly/) - Learn how to use.
- [Contribution](https://github.com/bigcapitalhq/bigcapital/blob/develop/CONTRIBUTING.md) - Welcome to any contributions.
- [Discord](https://discord.com/invite/c8nPBJafeb) - Ask for help.
- [Bug Tracker](https://github.com/bigcapitalhq/bigcapital/issues) - Notify us new bugs.
@@ -127,13 +124,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/asenawritescode"><img src="https://avatars.githubusercontent.com/u/67445192?v=4?s=100" width="100px;" alt="Asena"/><br /><sub><b>Asena</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Aasenawritescode" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://snyder.tech"><img src="https://avatars.githubusercontent.com/u/707567?v=4?s=100" width="100px;" alt="Ben Snyder"/><br /><sub><b>Ben Snyder</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=benpsnyder" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://vederis.id"><img src="https://avatars.githubusercontent.com/u/13505006?v=4?s=100" width="100px;" alt="Vederis Leunardus"/><br /><sub><b>Vederis Leunardus</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=cloudsbird" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.pivoten.com"><img src="https://avatars.githubusercontent.com/u/104120598?v=4?s=100" width="100px;" alt="Chris Cantrell"/><br /><sub><b>Chris Cantrell</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Accantrell72" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oleynikd"><img src="https://avatars.githubusercontent.com/u/3976868?v=4?s=100" width="100px;" alt="Denis"/><br /><sub><b>Denis</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Aoleynikd" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://myself.vercel.app/"><img src="https://avatars.githubusercontent.com/u/42431274?v=4?s=100" width="100px;" alt="Sachin Mittal"/><br /><sub><b>Sachin Mittal</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Amittalsam98" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.camilooviedo.com/"><img src="https://avatars.githubusercontent.com/u/64604272?v=4?s=100" width="100px;" alt="Camilo Oviedo"/><br /><sub><b>Camilo Oviedo</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/commits?author=Champetaman" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nklmantey.com/"><img src="https://avatars.githubusercontent.com/u/90279429?v=4?s=100" width="100px;" alt="Mantey"/><br /><sub><b>Mantey</b></sub></a><br /><a href="https://github.com/bigcapitalhq/bigcapital/issues?q=author%3Anklmantey" title="Bug reports">🐛</a></td>
</tr>
</tbody>
</table>

View File

@@ -3,31 +3,34 @@
version: '3.3'
services:
proxy:
image: envoyproxy/envoy:v1.30-latest
depends_on:
- server
- webapp
nginx:
container_name: bigcapital-nginx-gateway
build:
context: ./docker/nginx
args:
- SERVER_PROXY_PORT=3000
- WEB_SSL=false
- SELF_SIGNED=false
volumes:
- ./data/logs/nginx/:/var/log/nginx
- ./docker/certbot/certs/:/var/certs
ports:
- '${PUBLIC_PROXY_PORT:-80}:80'
- '${PUBLIC_PROXY_SSL_PORT:-443}:443'
tty: true
volumes:
- ./docker/envoy/envoy.yaml:/etc/envoy/envoy.yaml
depends_on:
- server
- webapp
restart: on-failure
networks:
- bigcapital_network
webapp:
container_name: bigcapital-webapp
image: bigcapitalhq/webapp:latest
image: ghcr.io/bigcapitalhq/webapp:latest
restart: on-failure
networks:
- bigcapital_network
server:
container_name: bigcapital-server
image: bigcapitalhq/server:latest
image: ghcr.io/bigcapitalhq/server:latest
expose:
- '3000'
links:
@@ -39,8 +42,6 @@ services:
- mongo
- redis
restart: on-failure
networks:
- bigcapital_network
environment:
# Mail
- MAIL_HOST=${MAIL_HOST}
@@ -81,24 +82,18 @@ services:
- SIGNUP_ALLOWED_DOMAINS=${SIGNUP_ALLOWED_DOMAINS}
- SIGNUP_ALLOWED_EMAILS=${SIGNUP_ALLOWED_EMAILS}
# Sign-up email confirmation
- SIGNUP_EMAIL_CONFIRMATION=${SIGNUP_EMAIL_CONFIRMATION}
# Gotenberg (Pdf generator)
- GOTENBERG_URL=${GOTENBERG_URL}
- GOTENBERG_DOCS_URL=${GOTENBERG_DOCS_URL}
# Exchange Rate
- EXCHANGE_RATE_SERVICE=${EXCHANGE_RATE_SERVICE}
- OPEN_EXCHANGE_RATE_APP_ID-${OPEN_EXCHANGE_RATE_APP_ID}
# Bank Sync
- BANKING_CONNECT=${BANKING_CONNECT}
# Plaid
- PLAID_ENV=${PLAID_ENV}
- PLAID_CLIENT_ID=${PLAID_CLIENT_ID}
- PLAID_SECRET=${PLAID_SECRET}
- PLAID_SECRET_DEVELOPMENT=${PLAID_SECRET_DEVELOPMENT}
- PLAID_SECRET_SANDBOX=${b8cf42b441e110451e2f69ad7e1e9f}
- PLAID_LINK_WEBHOOK=${PLAID_LINK_WEBHOOK}
# Lemon Squeez
@@ -107,22 +102,6 @@ services:
- LEMONSQUEEZY_WEBHOOK_SECRET=${LEMONSQUEEZY_WEBHOOK_SECRET}
- HOSTED_ON_BIGCAPITAL_CLOUD=${HOSTED_ON_BIGCAPITAL_CLOUD}
# New Relic matrics tracking.
- NEW_RELIC_DISTRIBUTED_TRACING_ENABLED=${NEW_RELIC_DISTRIBUTED_TRACING_ENABLED}
- NEW_RELIC_LOG=${NEW_RELIC_LOG}
- NEW_RELIC_AI_MONITORING_ENABLED=${NEW_RELIC_AI_MONITORING_ENABLED}
- NEW_RELIC_CUSTOM_INSIGHTS_EVENTS_MAX_SAMPLES_STORED=${NEW_RELIC_CUSTOM_INSIGHTS_EVENTS_MAX_SAMPLES_STORED}
- NEW_RELIC_SPAN_EVENTS_MAX_SAMPLES_STORED=${NEW_RELIC_SPAN_EVENTS_MAX_SAMPLES_STORED}
- NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY}
- NEW_RELIC_APP_NAME=${NEW_RELIC_APP_NAME}
# S3
- S3_REGION=${S3_REGION}
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
- S3_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY}
- S3_ENDPOINT=${S3_ENDPOINT}
- S3_BUCKET=${S3_BUCKET}
database_migration:
container_name: bigcapital-database-migration
build:
@@ -139,8 +118,6 @@ services:
- TENANT_DB_NAME_PERFIX=${TENANT_DB_NAME_PERFIX}
depends_on:
- mysql
networks:
- bigcapital_network
mysql:
container_name: bigcapital-mysql
@@ -156,8 +133,6 @@ services:
- mysql:/var/lib/mysql
expose:
- '3306'
networks:
- bigcapital_network
mongo:
container_name: bigcapital-mongo
@@ -167,8 +142,6 @@ services:
- '27017'
volumes:
- mongo:/var/lib/mongodb
networks:
- bigcapital_network
redis:
container_name: bigcapital-redis
@@ -179,15 +152,11 @@ services:
- '6379'
volumes:
- redis:/data
networks:
- bigcapital_network
gotenberg:
image: gotenberg/gotenberg:7
expose:
- '9000'
networks:
- bigcapital_network
# Volumes
volumes:
@@ -202,8 +171,3 @@ volumes:
redis:
name: bigcapital_prod_redis
driver: local
# Networks
networks:
bigcapital_network:
driver: bridge

View File

@@ -41,8 +41,6 @@ services:
context: ./docker/redis
expose:
- "6379"
ports:
- "6379:6379"
volumes:
- redis:/data
deploy:

View File

@@ -1,62 +0,0 @@
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ['*']
routes:
- match:
prefix: '/api'
route:
cluster: dynamic_server
- match:
prefix: '/'
route:
cluster: webapp
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: dynamic_server
connect_timeout: 0.25s
type: STRICT_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: dynamic_server
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: server
port_value: 3000
- name: webapp
connect_timeout: 0.25s
type: STRICT_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: webapp
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: webapp
port_value: 80

View File

@@ -1,4 +1,4 @@
FROM bigcapitalhq/server:latest as build
FROM ghcr.io/bigcapitalhq/server:latest as build
ARG DB_HOST= \
DB_USER= \
@@ -34,5 +34,7 @@ WORKDIR /app/packages/server
RUN git clone https://github.com/vishnubob/wait-for-it.git
# Once we listen the mysql port run the migration task.
CMD ./wait-for-it/wait-for-it.sh mysql:3306 -- sh -c "node ./build/commands.js system:migrate:latest && node ./build/commands.js tenants:migrate:latest"
ADD docker/migration/start.sh /
RUN chmod +x /start.sh
CMD ["/start.sh"]

View File

@@ -0,0 +1,5 @@
# Migrate the master system database.
./wait-for-it/wait-for-it.sh mysql:3306 -- node ./build/commands.js system:migrate:latest
# Migrate all tenants.
./wait-for-it/wait-for-it.sh mysql:3306 -- node ./build/commands.js tenants:migrate:latest

21
docker/nginx/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
FROM nginx:1.11
RUN mkdir /etc/nginx/sites-available && rm /etc/nginx/conf.d/default.conf
ADD nginx.conf /etc/nginx/
COPY scripts /root/scripts/
COPY certs /etc/ssl/
COPY sites /etc/nginx/templates
ARG SERVER_PROXY_PORT=3000
ARG WEB_SSL=false
ARG SELF_SIGNED=false
ENV SERVER_PROXY_PORT=$SERVER_PROXY_PORT
ENV WEB_SSL=$WEB_SSL
ENV SELF_SIGNED=$SELF_SIGNED
RUN /bin/bash /root/scripts/build-nginx.sh
CMD nginx

33
docker/nginx/nginx.conf Normal file
View File

@@ -0,0 +1,33 @@
user www-data;
worker_processes auto;
pid /run/nginx.pid;
daemon off;
events {
worker_connections 2048;
use epoll;
}
http {
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 15;
types_hash_max_size 2048;
client_max_body_size 20M;
open_file_cache max=100;
gzip on;
gzip_disable "msie6";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-available/*;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}

View File

@@ -0,0 +1,9 @@
#!/bin/bash
for conf in /etc/nginx/templates/*.conf; do
mv $conf "/etc/nginx/sites-available/"$(basename $conf) > /dev/null
done
for template in /etc/nginx/templates/*.template; do
envsubst < $template > "/etc/nginx/sites-available/"$(basename $template)".conf"
done

View File

@@ -0,0 +1,16 @@
server {
listen 80 default_server;
location /api {
proxy_pass http://server:${SERVER_PROXY_PORT};
}
location / {
proxy_pass http://webapp;
}
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt/;
log_not_found off;
}
}

View File

@@ -1,4 +1,4 @@
FROM redis:6.2.0
FROM redis:4.0
COPY redis.conf /usr/local/etc/redis/redis.conf

View File

@@ -1,24 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Nest Framework",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"start:debug",
"--",
"--inspect-brk"
],
"autoAttachChildProcesses": true,
"restart": true,
"sourceMaps": true,
"stopOnEntry": false,
"console": "integratedTerminal"
}
]
}

View File

@@ -3,7 +3,6 @@
"version": "independent",
"npmClient": "pnpm",
"packages": [
"packages/*",
"shared/*"
"packages/*"
]
}

View File

@@ -4,15 +4,12 @@
"scripts": {
"dev": "lerna run dev",
"build": "lerna run build",
"dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\"",
"build:webapp": "lerna run build --scope \"@bigcapital/webapp\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\"",
"dev:server": "lerna run dev --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\" --scope \"@bigcapital/email-components\"",
"build:server": "lerna run build --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\" --scope \"@bigcapital/pdf-templates\" --scope \"@bigcapital/email-components\"",
"serve:server": "lerna run serve --scope \"@bigcapital/server\" --scope \"@bigcapital/utils\"",
"server2:start": "lerna run start:dev --scope \"@bigcapital/server2\"",
"test:watch": "lerna run test:watch",
"test:e2e": "lerna run test:e2e",
"start:debug": "lerna run start:debug",
"dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\"",
"build:webapp": "lerna run build --scope \"@bigcapital/webapp\"",
"dev:server": "lerna run dev --scope \"@bigcapital/server\"",
"build:server": "lerna run build --scope \"@bigcapital/server\"",
"serve:server": "lerna run serve --scope \"@bigcapital/server\"",
"test:e2e": "playwright test",
"prepare": "husky install"
},
"devDependencies": {
@@ -32,8 +29,5 @@
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"dependencies": {
"tsup": "^8.3.0"
}
}

View File

@@ -1,105 +0,0 @@
# App
APP_JWT_SECRET=123123
# Mail
MAIL_HOST=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_PORT=
MAIL_SECURE=
MAIL_FROM_NAME=
MAIL_FROM_ADDRESS=
# Database
DB_HOST=localhost
DB_USER=bigcapital
DB_PASSWORD=bigcapital
DB_ROOT_PASSWORD=root
DB_CHARSET=utf8
# System database
SYSTEM_DB_NAME=bigcapital_system
# SYSTEM_DB_USER=
# SYSTEM_DB_PASSWORD=
# SYSTEM_DB_NAME=
# SYSTEM_DB_CHARSET=
# Tenant databases
TENANT_DB_NAME_PERFIX=bigcapital_tenant_
# TENANT_DB_HOST=
# TENANT_DB_USER=
# TENANT_DB_PASSWORD=
# TENANT_DB_CHARSET=
# Application
BASE_URL=http://example.com
JWT_SECRET=b0JDZW56RnV6aEthb0RGPXVEcUI
# Jobs MongoDB
MONGODB_DATABASE_URL=mongodb://localhost/bigcapital
# App proxy
PUBLIC_PROXY_PORT=80
PUBLIC_PROXY_SSL_PORT=443
# Agendash
AGENDASH_AUTH_USER=agendash
AGENDASH_AUTH_PASSWORD=123123
# Sign-up restrictions
SIGNUP_DISABLED=false
SIGNUP_ALLOWED_DOMAINS=
SIGNUP_ALLOWED_EMAILS=
# Sign-up Email Confirmation
SIGNUP_EMAIL_CONFIRMATION=false
# API rate limit (points,duration,block duration).
API_RATE_LIMIT=120,60,600
# Gotenberg API for PDF printing - (production).
GOTENBERG_URL=http://gotenberg:3000
GOTENBERG_DOCS_URL=http://server:3000/public/
# Gotenberg API - (development)
# GOTENBERG_URL=http://localhost:9000
# GOTENBERG_DOCS_URL=http://host.docker.internal:3000/public/
# Exchange Rate Service
EXCHANGE_RATE_SERVICE=open-exchange-rate
# Open Exchange Rate
OPEN_EXCHANGE_RATE_APP_ID=
# The Plaid environment to use ('sandbox' or 'development').
# https://plaid.com/docs/#api-host
PLAID_ENV=sandbox
# Your Plaid keys, which can be found in the Plaid Dashboard.
# https://dashboard.plaid.com/account/keys
PLAID_CLIENT_ID=
PLAID_SECRET=
PLAID_LINK_WEBHOOK=
# https://docs.lemonsqueezy.com/guides/developer-guide/getting-started#create-an-api-key
LEMONSQUEEZY_API_KEY=
LEMONSQUEEZY_STORE_ID=
LEMONSQUEEZY_WEBHOOK_SECRET=
# S3 documents and attachments
S3_REGION=US
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_ENDPOINT=
S3_BUCKET=
# PostHog
POSTHOG_API_KEY=
POSTHOG_HOST=
# Stripe Payment
STRIPE_PAYMENT_SECRET_KEY=
STRIPE_PAYMENT_PUBLISHABLE_KEY=
STRIPE_PAYMENT_CLIENT_ID=
STRIPE_PAYMENT_WEBHOOKS_SECRET=
STRIPE_PAYMENT_REDIRECT_URL=

View File

@@ -1,25 +0,0 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};

View File

@@ -1,56 +0,0 @@
# compiled output
/dist
/node_modules
/build
# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# OS
.DS_Store
# Tests
/coverage
/.nyc_output
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# temp directory
.temp
.tmp
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

View File

@@ -1,4 +0,0 @@
{
"singleQuote": true,
"trailingComma": "all"
}

View File

@@ -1 +0,0 @@
- Build authentication services.

View File

@@ -1 +0,0 @@
## @bigcapitalhq/server

View File

@@ -1,11 +0,0 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true,
"assets": [
{ "include": "i18n/**/*", "watchAssets": true }
]
}
}

View File

@@ -1,151 +0,0 @@
{
"name": "@bigcapital/server2",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json --watchAll"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.576.0",
"@aws-sdk/s3-request-presigner": "^3.583.0",
"@bigcapital/email-components": "*",
"@bigcapital/pdf-templates": "*",
"@bigcapital/utils": "*",
"@casl/ability": "^5.4.3",
"@lemonsqueezy/lemonsqueezy.js": "^2.2.0",
"@liaoliaots/nestjs-redis": "^10.0.0",
"@types/multer": "^1.4.11",
"@nestjs/bull": "^10.2.1",
"@nestjs/bullmq": "^10.2.2",
"@nestjs/cache-manager": "^2.2.2",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.0.0",
"@nestjs/event-emitter": "^2.0.4",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.4.2",
"@nestjs/throttler": "^6.2.1",
"@supercharge/promise-pool": "^3.2.0",
"@types/nodemailer": "^6.4.17",
"@types/passport-local": "^1.0.38",
"@types/ramda": "^0.30.2",
"accounting": "^0.4.1",
"async": "^3.2.0",
"async-mutex": "^0.5.0",
"axios": "^1.6.0",
"bcrypt": "^5.1.1",
"bcryptjs": "^2.4.3",
"bluebird": "^3.7.2",
"bull": "^4.16.3",
"bullmq": "^5.25.6",
"cache-manager": "^6.1.1",
"cache-manager-redis-store": "^3.0.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"deepdash": "^5.3.9",
"express-validator": "^7.2.0",
"form-data": "^4.0.0",
"fp-ts": "^2.16.9",
"ioredis": "^5.6.0",
"is-my-json-valid": "^2.20.5",
"js-money": "^0.6.3",
"knex": "^3.1.0",
"lamda": "^0.4.1",
"lodash": "^4.17.21",
"lru-cache": "^6.0.0",
"mathjs": "^9.4.0",
"mime-types": "^2.1.35",
"moment": "^2.30.1",
"moment-range": "^4.0.2",
"moment-timezone": "^0.5.43",
"mysql": "^2.18.1",
"mysql2": "^3.11.3",
"multer": "1.4.5-lts.1",
"multer-s3": "^3.0.1",
"nestjs-cls": "^5.2.0",
"nestjs-i18n": "^10.4.9",
"nestjs-redis": "^1.3.3",
"nodemailer": "^6.3.0",
"object-hash": "^2.0.3",
"objection": "^3.1.5",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"plaid": "^10.3.0",
"pluralize": "^8.0.0",
"posthog-node": "^4.3.2",
"pug": "^3.0.2",
"ramda": "^0.30.1",
"redis": "^4.7.0",
"reflect-metadata": "^0.2.0",
"remeda": "^2.19.2",
"rxjs": "^7.8.1",
"serialize-interceptor": "^1.1.7",
"strategy": "^1.1.1",
"stripe": "^16.10.0",
"uniqid": "^5.2.0",
"uuid": "^10.0.0",
"xlsx": "^0.18.5",
"yup": "^0.28.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^5.0.0",
"@types/jest": "^29.5.2",
"@types/mathjs": "^6.0.12",
"@types/node": "^20.3.1",
"@types/supertest": "^6.0.0",
"@types/yup": "^0.29.13",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"mustache": "^3.0.3",
"prettier": "^3.0.0",
"source-map-support": "^0.5.21",
"supertest": "^7.0.0",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}

View File

@@ -1,6 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('gotenberg', () => ({
url: process.env.GOTENBERG_URL,
docsUrl: process.env.GOTENBERG_DOCS_URL,
}));

View File

@@ -1,33 +0,0 @@
import systemDatabase from './system-database';
import tenantDatabase from './tenant-database';
import signup from './signup';
import gotenberg from './gotenberg';
import plaid from './plaid';
import lemonsqueezy from './lemonsqueezy';
import s3 from './s3';
import openExchange from './open-exchange';
import posthog from './posthog';
import stripePayment from './stripe-payment';
import signupConfirmation from './signup-confirmation';
import signupRestrictions from './signup-restrictions';
import jwt from './jwt';
import mail from './mail';
import loops from './loops';
export const config = [
systemDatabase,
tenantDatabase,
signup,
gotenberg,
plaid,
lemonsqueezy,
s3,
openExchange,
posthog,
stripePayment,
signupConfirmation,
signupRestrictions,
jwt,
mail,
loops
];

View File

@@ -1,5 +0,0 @@
import { registerAs } from "@nestjs/config";
export default registerAs('inventory', () => ({
scheduleComputeItemCost: process.env.INVENTORY_SCHEDULE_COMPUTE_ITEM_COST,
}));

View File

@@ -1,5 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('jwt', () => ({
secret: process.env.APP_JWT_SECRET || '123123',
}));

View File

@@ -1,7 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('lemonsqueezy', () => ({
apiKey: process.env.LEMONSQUEEZY_API_KEY,
storeId: process.env.LEMONSQUEEZY_STORE_ID,
webhookSecret: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
}));

View File

@@ -1,6 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('loops', () => ({
apiKey: process.env.LOOPS_API_KEY,
}));

View File

@@ -1,13 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('mail', () => ({
host: process.env.MAIL_HOST,
username: process.env.MAIL_USERNAME,
password: process.env.MAIL_PASSWORD,
port: parseInt(process.env.MAIL_PORT, 10),
secure: process.env.MAIL_SECURE === 'true',
from: {
name: process.env.MAIL_FROM_NAME,
address: process.env.MAIL_FROM_ADDRESS,
},
}));

View File

@@ -1,5 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('openExchange', () => ({
appId: process.env.OPEN_EXCHANGE_RATE_APP_ID,
}));

View File

@@ -1,8 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('plaid', () => ({
env: process.env.PLAID_ENV || 'sandbox',
clientId: process.env.PLAID_CLIENT_ID,
secret: process.env.PLAID_SECRET,
linkWebhook: process.env.PLAID_LINK_WEBHOOK,
}));

View File

@@ -1,6 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('posthog', () => ({
apiKey: process.env.POSTHOG_API_KEY,
host: process.env.POSTHOG_HOST || 'https://us.i.posthog.com',
}));

View File

@@ -1,8 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('redis', () => ({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT, 10) || 6379,
password: process.env.REDIS_PASSWORD || undefined,
db: parseInt(process.env.REDIS_DB, 10) || 0,
}));

View File

@@ -1,9 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('s3', () => ({
region: process.env.S3_REGION || 'US',
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
endpoint: process.env.S3_ENDPOINT,
bucket: process.env.S3_BUCKET,
}));

View File

@@ -1,6 +0,0 @@
import { parseBoolean } from '@/utils/parse-boolean';
import { registerAs } from '@nestjs/config';
export default registerAs('signupConfirmation', () => ({
enabled: parseBoolean<boolean>(process.env.SIGNUP_EMAIL_CONFIRMATION, false),
}));

View File

@@ -1,11 +0,0 @@
import { castCommaListEnvVarToArray } from '@/utils/cast-comma-list-envvar-Array';
import { parseBoolean } from '@/utils/parse-boolean';
import { registerAs } from '@nestjs/config';
export default registerAs('signupRestrictions', () => ({
disabled: parseBoolean<boolean>(process.env.SIGNUP_DISABLED, false),
allowedDomains: castCommaListEnvVarToArray(
process.env.SIGNUP_ALLOWED_DOMAINS,
),
allowedEmails: castCommaListEnvVarToArray(process.env.SIGNUP_ALLOWED_EMAILS),
}));

View File

@@ -1,12 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('signup', () => ({
disabled: process.env.SIGNUP_DISABLED === 'true',
allowedDomains: process.env.SIGNUP_ALLOWED_DOMAINS
? process.env.SIGNUP_ALLOWED_DOMAINS.split(',')
: [],
allowedEmails: process.env.SIGNUP_ALLOWED_EMAILS
? process.env.SIGNUP_ALLOWED_EMAILS.split(',')
: [],
emailConfirmation: process.env.SIGNUP_EMAIL_CONFIRMATION === 'true',
}));

View File

@@ -1,9 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('stripePayment', () => ({
secretKey: process.env.STRIPE_PAYMENT_SECRET_KEY,
publishableKey: process.env.STRIPE_PAYMENT_PUBLISHABLE_KEY,
clientId: process.env.STRIPE_PAYMENT_CLIENT_ID,
webhooksSecret: process.env.STRIPE_PAYMENT_WEBHOOKS_SECRET,
redirectUrl: process.env.STRIPE_PAYMENT_REDIRECT_URL,
}));

View File

@@ -1,10 +0,0 @@
import { registerAs } from '@nestjs/config';
export default registerAs('systemDatabase', () => ({
client: 'mysql',
host: process.env.SYSTEM_DB_HOST || process.env.DB_HOST,
port: process.env.SYSTEM_DB_PORT || process.env.DB_PORT || 5432,
user: process.env.SYSTEM_DB_USER || process.env.DB_USER,
password: process.env.SYSTEM_DB_PASSWORD || process.env.DB_PASSWORD,
databaseName: process.env.SYSTEM_DB_NAME || process.env.DB_NAME,
}));

View File

@@ -1,13 +0,0 @@
import * as path from 'path';
import { registerAs } from '@nestjs/config';
export default registerAs('tenantDatabase', () => ({
client: 'mysql',
host: process.env.TENANT_DB_HOST || process.env.DB_HOST,
port: process.env.TENANT_DB_PORT || process.env.DB_PORT || 5432,
user: process.env.TENANT_DB_USER || process.env.DB_USER,
password: process.env.TENANT_DB_PASSWORD || process.env.DB_PASSWORD,
dbNamePrefix: process.env.TENANT_DB_NAME_PERFIX || 'bigcapital_tenant_',
migrationsDir: path.join(__dirname, '../../database/migrations'),
seedsDir: path.join(__dirname, '../../database/seeds/core'),
}));

View File

@@ -1 +0,0 @@
export const MULTER_MODULE_OPTIONS = 'MULTER_MODULE_OPTIONS';

View File

@@ -1,24 +0,0 @@
import type { Multer } from 'multer';
import * as multerS3 from 'multer-s3';
export const multerExceptions = {
// from https://github.com/expressjs/multer/blob/master/lib/multer-error.js
LIMIT_PART_COUNT: 'Too many parts',
LIMIT_FILE_SIZE: 'File too large',
LIMIT_FILE_COUNT: 'Too many files',
LIMIT_FIELD_KEY: 'Field name too long',
LIMIT_FIELD_VALUE: 'Field value too long',
LIMIT_FIELD_COUNT: 'Too many fields',
LIMIT_UNEXPECTED_FILE: 'Unexpected field',
MISSING_FIELD_NAME: 'Field name missing',
};
export const busboyExceptions = {
// from https://github.com/mscdex/busboy/blob/master/lib/types/multipart.js
MULTIPART_BOUNDARY_NOT_FOUND: 'Multipart: Boundary not found',
MULTIPART_MALFORMED_PART_HEADER: 'Malformed part header',
MULTIPART_UNEXPECTED_END_OF_FORM: 'Unexpected end of form',
MULTIPART_UNEXPECTED_END_OF_FILE: 'Unexpected end of file',
};

View File

@@ -1,38 +0,0 @@
import {
BadRequestException,
HttpException,
PayloadTooLargeException,
} from '@nestjs/common';
import { multerExceptions, busboyExceptions } from './multer.constants';
// Multer may add in a 'field' property to the error
// https://github.com/expressjs/multer/blob/aa42bea6ac7d0cb8fcb279b15a7278cda805dc63/lib/multer-error.js#L19
export function transformException(
error: (Error & { field?: string }) | undefined,
) {
if (!error || error instanceof HttpException) {
return error;
}
switch (error.message) {
case multerExceptions.LIMIT_FILE_SIZE:
return new PayloadTooLargeException(error.message);
case multerExceptions.LIMIT_FILE_COUNT:
case multerExceptions.LIMIT_FIELD_KEY:
case multerExceptions.LIMIT_FIELD_VALUE:
case multerExceptions.LIMIT_FIELD_COUNT:
case multerExceptions.LIMIT_UNEXPECTED_FILE:
case multerExceptions.LIMIT_PART_COUNT:
case multerExceptions.MISSING_FIELD_NAME:
if (error.field) {
return new BadRequestException(`${error.message} - ${error.field}`);
}
return new BadRequestException(error.message);
case busboyExceptions.MULTIPART_BOUNDARY_NOT_FOUND:
return new BadRequestException(error.message);
case busboyExceptions.MULTIPART_MALFORMED_PART_HEADER:
case busboyExceptions.MULTIPART_UNEXPECTED_END_OF_FORM:
case busboyExceptions.MULTIPART_UNEXPECTED_END_OF_FILE:
return new BadRequestException(`Multipart: ${error.message}`);
}
return error;
}

View File

@@ -1,775 +0,0 @@
export const events = {
/**
* Authentication service.
*/
auth: {
signIn: 'onSignIn',
signingIn: 'onSigningIn',
signUp: 'onSignUp',
signingUp: 'onSigningUp',
signUpConfirming: 'signUpConfirming',
signUpConfirmed: 'signUpConfirmed',
sendingResetPassword: 'onSendingResetPassword',
sendResetPassword: 'onSendResetPassword',
resetPassword: 'onResetPassword',
resetingPassword: 'onResetingPassword',
},
/**
* Invite users service.
*/
inviteUser: {
acceptInvite: 'onUserAcceptInvite',
sendInvite: 'onUserSendInvite',
resendInvite: 'onUserInviteResend',
checkInvite: 'onUserCheckInvite',
sendInviteTenantSynced: 'onUserSendInviteTenantSynced',
},
/**
* Organization managment service.
*/
organization: {
build: 'onOrganizationBuild',
built: 'onOrganizationBuilt',
seeded: 'onOrganizationSeeded',
baseCurrencyUpdated: 'onOrganizationBaseCurrencyUpdated',
},
/**
* Organization subscription.
*/
subscription: {
onSubscriptionCancel: 'onSubscriptionCancel',
onSubscriptionCancelled: 'onSubscriptionCancelled',
onSubscriptionResume: 'onSubscriptionResume',
onSubscriptionResumed: 'onSubscriptionResumed',
onSubscriptionPlanChange: 'onSubscriptionPlanChange',
onSubscriptionPlanChanged: 'onSubscriptionPlanChanged',
onSubscriptionSubscribed: 'onSubscriptionSubscribed',
onSubscriptionPaymentSucceed: 'onSubscriptionPaymentSucceed',
onSubscriptionPaymentFailed: 'onSubscriptionPaymentFailed',
},
/**
* Tenants managment service.
*/
tenantManager: {
databaseCreated: 'onDatabaseCreated',
tenantMigrated: 'onTenantMigrated',
tenantSeeded: 'onTenantSeeded',
},
/**
* Accounts service.
*/
accounts: {
onViewed: 'onAccountViewed',
onListViewed: 'onAccountsListViewed',
onCreating: 'onAccountCreating',
onCreated: 'onAccountCreated',
onEditing: 'onAccountEditing',
onEdited: 'onAccountEdited',
onDelete: 'onAccountDelete',
onDeleted: 'onAccountDeleted',
onBulkDeleted: 'onBulkDeleted',
onBulkActivated: 'onAccountBulkActivated',
onActivated: 'onAccountActivated',
},
/**
* Manual journals service.
*/
manualJournals: {
onCreating: 'onManualJournalCreating',
onCreated: 'onManualJournalCreated',
onEditing: 'onManualJournalEditing',
onEdited: 'onManualJournalEdited',
onDeleting: 'onManualJournalDeleting',
onDeleted: 'onManualJournalDeleted',
onPublished: 'onManualJournalPublished',
onPublishing: 'onManualJournalPublishing',
},
/**
* Expenses service.
*/
expenses: {
onCreating: 'onExpenseCreating',
onCreated: 'onExpenseCreated',
onEditing: 'onExpenseEditing',
onEdited: 'onExpenseEdited',
onDeleting: 'onExpenseDeleting',
onDeleted: 'onExpenseDeleted',
onPublishing: 'onExpensePublishing',
onPublished: 'onExpensePublished',
},
/**
* Sales invoices service.
*/
saleInvoice: {
onViewed: 'onSaleInvoiceItemViewed',
onListViewed: 'onSaleInvoiceListViewed',
onPdfViewed: 'onSaleInvoicePdfViewed',
onCreate: 'onSaleInvoiceCreate',
onCreating: 'onSaleInvoiceCreating',
onCreated: 'onSaleInvoiceCreated',
onEdit: 'onSaleInvoiceEdit',
onEditing: 'onSaleInvoiceEditing',
onEdited: 'onSaleInvoiceEdited',
onDelete: 'onSaleInvoiceDelete',
onDeleting: 'onSaleInvoiceDeleting',
onDeleted: 'onSaleInvoiceDeleted',
onDelivering: 'onSaleInvoiceDelivering',
onDeliver: 'onSaleInvoiceDeliver',
onDelivered: 'onSaleInvoiceDelivered',
onPublish: 'onSaleInvoicePublish',
onPublished: 'onSaleInvoicePublished',
onWriteoff: 'onSaleInvoiceWriteoff',
onWrittenoff: 'onSaleInvoiceWrittenoff',
onWrittenoffCancel: 'onSaleInvoiceWrittenoffCancel',
onWrittenoffCanceled: 'onSaleInvoiceWrittenoffCanceled',
onNotifySms: 'onSaleInvoiceNotifySms',
onNotifiedSms: 'onSaleInvoiceNotifiedSms',
onNotifyMail: 'onSaleInvoiceNotifyMail',
onNotifyReminderMail: 'onSaleInvoiceNotifyReminderMail',
onPreMailSend: 'onSaleInvoicePreMailSend',
onMailSend: 'onSaleInvoiceMailSend',
onMailSent: 'onSaleInvoiceMailSent',
onMailReminderSend: 'onSaleInvoiceMailReminderSend',
onMailReminderSent: 'onSaleInvoiceMailReminderSent',
onPublicLinkGenerating: 'onPublicSharableLinkGenerating',
onPublicLinkGenerated: 'onPublicSharableLinkGenerated',
},
/**
* Sales estimates service.
*/
saleEstimate: {
onViewed: 'onSaleEstimateViewed',
onPdfViewed: 'onSaleEstimatePdfViewed',
onCreating: 'onSaleEstimateCreating',
onCreated: 'onSaleEstimateCreated',
onEditing: 'onSaleEstimateEditing',
onEdited: 'onSaleEstimateEdited',
onDeleting: 'onSaleEstimatedDeleting',
onDeleted: 'onSaleEstimatedDeleted',
onPublishing: 'onSaleEstimatedPublishing',
onPublished: 'onSaleEstimatedPublished',
onNotifySms: 'onSaleEstimateNotifySms',
onNotifiedSms: 'onSaleEstimateNotifiedSms',
onDelivering: 'onSaleEstimateDelivering',
onDelivered: 'onSaleEstimateDelivered',
onConvertedToInvoice: 'onSaleEstimateConvertedToInvoice',
onApproving: 'onSaleEstimateApproving',
onApproved: 'onSaleEstimateApproved',
onRejecting: 'onSaleEstimateRejecting',
onRejected: 'onSaleEstimateRejected',
onNotifyMail: 'onSaleEstimateNotifyMail',
onPreMailSend: 'onSaleEstimatePreMailSend',
onMailSend: 'onSaleEstimateMailSend',
onMailSent: 'onSaleEstimateMailSent',
},
/**
* Sales receipts service.
*/
saleReceipt: {
onPdfViewed: 'onSaleReceiptPdfViewed',
onCreating: 'onSaleReceiptsCreating',
onCreated: 'onSaleReceiptsCreated',
onEditing: 'onSaleReceiptsEditing',
onEdited: 'onSaleReceiptsEdited',
onDeleting: 'onSaleReceiptsDeleting',
onDeleted: 'onSaleReceiptsDeleted',
onPublishing: 'onSaleReceiptPublishing',
onPublished: 'onSaleReceiptPublished',
onClosed: 'onSaleReceiptClosed',
onClosing: 'onSaleReceiptClosing',
onNotifySms: 'onSaleReceiptNotifySms',
onNotifiedSms: 'onSaleReceiptNotifiedSms',
onPreMailSend: 'onSaleReceiptPreMailSend',
onMailSend: 'onSaleReceiptMailSend',
onMailSent: 'onSaleReceiptMailSent',
},
/**
* Payment receipts service.
*/
paymentReceive: {
onPdfViewed: 'onPaymentReceivedPdfViewed',
onCreated: 'onPaymentReceiveCreated',
onCreating: 'onPaymentReceiveCreating',
onEditing: 'onPaymentReceiveEditing',
onEdited: 'onPaymentReceiveEdited',
onDeleting: 'onPaymentReceiveDeleting',
onDeleted: 'onPaymentReceiveDeleted',
onPublishing: 'onPaymentReceivePublishing',
onPublished: 'onPaymentReceivePublished',
onNotifySms: 'onPaymentReceiveNotifySms',
onNotifiedSms: 'onPaymentReceiveNotifiedSms',
onPreMailSend: 'onPaymentReceivePreMailSend',
onMailSend: 'onPaymentReceiveMailSend',
onMailSent: 'onPaymentReceiveMailSent',
},
/**
* Bills service.
*/
bill: {
onCreating: 'onBillCreating',
onCreated: 'onBillCreated',
onEditing: 'onBillEditing',
onEdited: 'onBillEdited',
onDeleting: 'onBillDeleting',
onDeleted: 'onBillDeleted',
onPublishing: 'onBillPublishing',
onPublished: 'onBillPublished',
onOpening: 'onBillOpening',
onOpened: 'onBillOpened',
},
/**
* Bill payments service.
*/
billPayment: {
onCreating: 'onBillPaymentCreating',
onCreated: 'onBillPaymentCreated',
onEditing: 'onBillPaymentEditing',
onEdited: 'onBillPaymentEdited',
onDeleted: 'onBillPaymentDeleted',
onDeleting: 'onBillPaymentDeleting',
onPublishing: 'onBillPaymentPublishing',
onPublished: 'onBillPaymentPublished',
},
/**
* Customers services.
*/
customers: {
onCreating: 'onCustomerCreating',
onCreated: 'onCustomerCreated',
onEdited: 'onCustomerEdited',
onEditing: 'onCustomerEditing',
onDeleted: 'onCustomerDeleted',
onDeleting: 'onCustomerDeleting',
onBulkDeleted: 'onBulkDeleted',
onOpeningBalanceChanging: 'onCustomerOpeningBalanceChanging',
onOpeningBalanceChanged: 'onCustomerOpeingBalanceChanged',
onActivating: 'onCustomerActivating',
onActivated: 'onCustomerActivated',
},
/**
* Vendors services.
*/
vendors: {
onCreated: 'onVendorCreated',
onCreating: 'onVendorCreating',
onEdited: 'onVendorEdited',
onEditing: 'onVendorEditing',
onDeleted: 'onVendorDeleted',
onDeleting: 'onVendorDeleting',
onOpeningBalanceChanging: 'onVendorOpeingBalanceChanging',
onOpeningBalanceChanged: 'onVendorOpeingBalanceChanged',
onActivating: 'onVendorActivating',
onActivated: 'onVendorActivated',
},
/**
* Items service.
*/
item: {
onViewed: 'onItemViewed',
onCreated: 'onItemCreated',
onCreating: 'onItemCreating',
onEditing: 'onItemEditing',
onEdited: 'onItemEdited',
onDeleted: 'onItemDeleted',
onDeleting: 'onItemDeleting',
onActivating: 'onItemActivating',
onActivated: 'onItemActivated',
onInactivating: 'onInactivating',
onInactivated: 'onItemInactivated',
},
/**
* Item category service.
*/
itemCategory: {
onCreated: 'onItemCategoryCreated',
onEdited: 'onItemCategoryEdited',
onDeleted: 'onItemCategoryDeleted',
onBulkDeleted: 'onItemCategoryBulkDeleted',
},
/**
* Inventory service.
*/
inventory: {
onInventoryTransactionsCreated: 'onInventoryTransactionsCreated',
onInventoryTransactionsDeleted: 'onInventoryTransactionsDeleted',
onComputeItemCostJobScheduled: 'onComputeItemCostJobScheduled',
onComputeItemCostJobStarted: 'onComputeItemCostJobStarted',
onComputeItemCostJobCompleted: 'onComputeItemCostJobCompleted',
onInventoryCostEntriesWritten: 'onInventoryCostEntriesWritten',
onCostLotsGLEntriesBeforeWrite: 'onInventoryCostLotsGLEntriesBeforeWrite',
onCostLotsGLEntriesWrite: 'onInventoryCostLotsGLEntriesWrite',
},
/**
* Inventory adjustment service.
*/
inventoryAdjustment: {
onQuickCreating: 'onInventoryAdjustmentCreating',
onQuickCreated: 'onInventoryAdjustmentQuickCreated',
onCreated: 'onInventoryAdjustmentCreated',
onDeleting: 'onInventoryAdjustmentDeleting',
onDeleted: 'onInventoryAdjustmentDeleted',
onPublishing: 'onInventoryAdjustmentPublishing',
onPublished: 'onInventoryAdjustmentPublished',
},
/**
* Bill landed cost.
*/
billLandedCost: {
onCreate: 'onBillLandedCostCreate',
onCreated: 'onBillLandedCostCreated',
onDelete: 'onBillLandedCostDelete',
onDeleted: 'onBillLandedCostDeleted',
},
cashflow: {
onOwnerContributionCreate: 'onCashflowOwnerContributionCreate',
onOwnerContributionCreated: 'onCashflowOwnerContributionCreated',
onOtherIncomeCreate: 'onCashflowOtherIncomeCreate',
onOtherIncomeCreated: 'onCashflowOtherIncomeCreated',
onTransactionCreating: 'onCashflowTransactionCreating',
onTransactionCreated: 'onCashflowTransactionCreated',
onTransactionDeleting: 'onCashflowTransactionDeleting',
onTransactionDeleted: 'onCashflowTransactionDeleted',
onTransactionCategorizing: 'onTransactionCategorizing',
onTransactionCategorized: 'onCashflowTransactionCategorized',
onTransactionUncategorizedCreating: 'onTransactionUncategorizedCreating',
onTransactionUncategorizedCreated: 'onTransactionUncategorizedCreated',
onTransactionUncategorizing: 'onTransactionUncategorizing',
onTransactionUncategorized: 'onTransactionUncategorized',
onTransactionCategorizingAsExpense: 'onTransactionCategorizingAsExpense',
onTransactionCategorizedAsExpense: 'onTransactionCategorizedAsExpense',
},
/**
* Roles service events.
*/
roles: {
onCreate: 'onRoleCreate',
onCreated: 'onRoleCreated',
onEdit: 'onRoleEdit',
onEdited: 'onRoleEdited',
onDelete: 'onRoleDelete',
onDeleted: 'onRoleDeleted',
},
tenantUser: {
onEdited: 'onTenantUserEdited',
onDeleted: 'onTenantUserDeleted',
onActivated: 'onTenantUserActivated',
onInactivated: 'onTenantUserInactivated',
},
/**
* Credit note service.
*/
creditNote: {
onPdfViewed: 'onCreditNotePdfViewed',
onCreate: 'onCreditNoteCreate',
onCreating: 'onCreditNoteCreating',
onCreated: 'onCreditNoteCreated',
onEditing: 'onCreditNoteEditing',
onEdit: 'onCreditNoteEdit',
onEdited: 'onCreditNoteEdited',
onDelete: 'onCreditNoteDelete',
onDeleting: 'onCreditNoteDeleting',
onDeleted: 'onCreditNoteDeleted',
onOpen: 'onCreditNoteOpen',
onOpening: 'onCreditNoteOpening',
onOpened: 'onCreditNoteOpened',
onRefundCreate: 'onCreditNoteRefundCreate',
onRefundCreating: 'onCreditNoteRefundCreating',
onRefundCreated: 'onCreditNoteRefundCreated',
onRefundDelete: 'onCreditNoteRefundDelete',
onRefundDeleting: 'onCreditNoteRefundDeleting',
onRefundDeleted: 'onCreditNoteRefundDeleted',
onApplyToInvoicesCreated: 'onCreditNoteApplyToInvoiceCreated',
onApplyToInvoicesCreate: 'onCreditNoteApplyToInvoiceCreate',
onApplyToInvoicesDeleted: 'onCreditNoteApplyToInvoiceDeleted',
},
/**
* Vendor credit service.
*/
vendorCredit: {
onCreate: 'onVendorCreditCreate',
onCreating: 'onVendorCreditCreating',
onCreated: 'onVendorCreditCreated',
onEdit: 'onVendorCreditEdit',
onEditing: 'onVendorCreditEditing',
onEdited: 'onVendorCreditEdited',
onDelete: 'onVendorCreditDelete',
onDeleting: 'onVendorCreditDeleting',
onDeleted: 'onVendorCreditDeleted',
onOpen: 'onVendorCreditOpen',
onOpened: 'onVendorCreditOpened',
onRefundCreating: 'onVendorCreditRefundCreating',
onRefundCreate: 'onVendorCreditRefundCreate',
onRefundCreated: 'onVendorCreditRefundCreated',
onRefundDelete: 'onVendorCreditRefundDelete',
onRefundDeleting: 'onVendorCreditRefundDeleting',
onRefundDeleted: 'onVendorCreditRefundDeleted',
onApplyToInvoicesCreated: 'onVendorCreditApplyToInvoiceCreated',
onApplyToInvoicesCreate: 'onVendorCreditApplyToInvoiceCreate',
onApplyToInvoicesDeleted: 'onVendorCreditApplyToInvoiceDeleted',
},
transactionsLocking: {
locked: 'onTransactionLockingLocked',
lockCanceled: 'onTransactionLockingLockCanceled',
partialUnlocked: 'onTransactionLockingPartialUnlocked',
partialUnlockCanceled: 'onTransactionLockingPartialUnlockCanceled',
},
warehouse: {
onCreate: 'onWarehouseCreate',
onCreated: 'onWarehouseCreated',
onEdit: 'onWarehouseEdit',
onEdited: 'onWarehouseEdited',
onDelete: 'onWarehouseDelete',
onDeleted: 'onWarehouseDeleted',
onActivate: 'onWarehouseActivate',
onActivated: 'onWarehouseActivated',
onMarkPrimary: 'onWarehouseMarkPrimary',
onMarkedPrimary: 'onWarehouseMarkedPrimary',
},
warehouseTransfer: {
onCreate: 'onWarehouseTransferCreate',
onCreated: 'onWarehouseTransferCreated',
onEdit: 'onWarehouseTransferEdit',
onEdited: 'onWarehouseTransferEdited',
onDelete: 'onWarehouseTransferDelete',
onDeleted: 'onWarehouseTransferDeleted',
onInitiate: 'onWarehouseTransferInitiate',
onInitiated: 'onWarehouseTransferInitated',
onTransfer: 'onWarehouseTransferInitiate',
onTransferred: 'onWarehouseTransferTransferred',
},
/**
* Branches.
*/
branch: {
onActivate: 'onBranchActivate',
onActivated: 'onBranchActivated',
onMarkPrimary: 'onBranchMarkPrimary',
onMarkedPrimary: 'onBranchMarkedPrimary',
},
/**
* Projects.
*/
project: {
onCreate: 'onProjectCreate',
onCreating: 'onProjectCreating',
onCreated: 'onProjectCreated',
onEdit: 'onEditProject',
onEditing: 'onEditingProject',
onEdited: 'onEditedProject',
onEditStatus: 'onEditStatusProject',
onEditingStatus: 'onEditingStatusProject',
onEditedStatus: 'onEditedStatusProject',
onDelete: 'onDeleteProject',
onDeleting: 'onDeletingProject',
onDeleted: 'onDeletedProject',
},
/**
* Project Tasks.
*/
projectTask: {
onCreate: 'onProjectTaskCreate',
onCreating: 'onProjectTaskCreating',
onCreated: 'onProjectTaskCreated',
onEdit: 'onProjectTaskEdit',
onEditing: 'onProjectTaskEditing',
onEdited: 'onProjectTaskEdited',
onDelete: 'onProjectTaskDelete',
onDeleting: 'onProjectTaskDeleting',
onDeleted: 'onProjectTaskDeleted',
},
/**
* Project Times.
*/
projectTime: {
onCreate: 'onProjectTimeCreate',
onCreating: 'onProjectTimeCreating',
onCreated: 'onProjectTimeCreated',
onEdit: 'onProjectTimeEdit',
onEditing: 'onProjectTimeEditing',
onEdited: 'onProjectTimeEdited',
onDelete: 'onProjectTimeDelete',
onDeleting: 'onProjectTimeDeleting',
onDeleted: 'onProjectTimeDeleted',
},
taxRates: {
onCreating: 'onTaxRateCreating',
onCreated: 'onTaxRateCreated',
onEditing: 'onTaxRateEditing',
onEdited: 'onTaxRateEdited',
onDeleting: 'onTaxRateDeleting',
onDeleted: 'onTaxRateDeleted',
onActivating: 'onTaxRateActivating',
onActivated: 'onTaxRateActivated',
onInactivating: 'onTaxRateInactivating',
onInactivated: 'onTaxRateInactivated',
},
plaid: {
onItemCreated: 'onPlaidItemCreated',
onTransactionsSynced: 'onPlaidTransactionsSynced',
},
// Bank rules.
bankRules: {
onCreating: 'onBankRuleCreating',
onCreated: 'onBankRuleCreated',
onEditing: 'onBankRuleEditing',
onEdited: 'onBankRuleEdited',
onDeleting: 'onBankRuleDeleting',
onDeleted: 'onBankRuleDeleted',
},
// Bank matching.
bankMatch: {
onMatching: 'onBankTransactionMatching',
onMatched: 'onBankTransactionMatched',
onUnmatching: 'onBankTransactionUnmathcing',
onUnmatched: 'onBankTransactionUnmathced',
},
bankTransactions: {
onExcluding: 'onBankTransactionExclude',
onExcluded: 'onBankTransactionExcluded',
onUnexcluding: 'onBankTransactionUnexcluding',
onUnexcluded: 'onBankTransactionUnexcluded',
onPendingRemoving: 'onBankTransactionPendingRemoving',
onPendingRemoved: 'onBankTransactionPendingRemoved',
},
bankAccount: {
onDisconnecting: 'onBankAccountDisconnecting',
onDisconnected: 'onBankAccountDisconnected',
},
// Import files.
import: {
onImportCommitted: 'onImportFileCommitted',
},
// Branding templates
pdfTemplate: {
onCreating: 'onPdfTemplateCreating',
onCreated: 'onPdfTemplateCreated',
onEditing: 'onPdfTemplateEditing',
onEdited: 'onPdfTemplatedEdited',
onDeleting: 'onPdfTemplateDeleting',
onDeleted: 'onPdfTemplateDeleted',
onAssignedDefault: 'onPdfTemplateAssignedDefault',
onAssigningDefault: 'onPdfTemplateAssigningDefault',
},
// Payment method.
paymentMethod: {
onEditing: 'onPaymentMethodEditing',
onEdited: 'onPaymentMethodEdited',
onDeleted: 'onPaymentMethodDeleted',
},
// Payment methods integrations
paymentIntegrationLink: {
onPaymentIntegrationLink: 'onPaymentIntegrationLink',
onPaymentIntegrationDeleteLink: 'onPaymentIntegrationDeleteLink',
},
// Stripe Payment Integration
stripeIntegration: {
onAccountCreated: 'onStripeIntegrationAccountCreated',
onAccountDeleted: 'onStripeIntegrationAccountDeleted',
onPaymentLinkCreated: 'onStripePaymentLinkCreated',
onPaymentLinkInactivated: 'onStripePaymentLinkInactivated',
onOAuthCodeGranted: 'onStripeOAuthCodeGranted',
},
// Stripe Payment Webhooks
stripeWebhooks: {
onCheckoutSessionCompleted: 'onStripeCheckoutSessionCompleted',
onAccountUpdated: 'onStripeAccountUpdated',
},
// Reports
reports: {
onBalanceSheetViewed: 'onBalanceSheetViewed',
onTrialBalanceSheetView: 'onTrialBalanceSheetViewed',
onProfitLossSheetViewed: 'onProfitLossSheetViewed',
onCashflowStatementViewed: 'onCashflowStatementViewed',
onGeneralLedgerViewed: 'onGeneralLedgerViewed',
onJournalViewed: 'onJounralViewed',
onReceivableAgingViewed: 'onReceivableAgingViewed',
onPayableAgingViewed: 'onPayableAgingViewed',
onCustomerBalanceSummaryViewed: 'onInventoryValuationViewed',
onVendorBalanceSummaryViewed: 'onVendorBalanceSummaryViewed',
onInventoryValuationViewed: 'onCustomerBalanceSummaryViewed',
onCustomerTransactionsViewed: 'onCustomerTransactionsViewed',
onVendorTransactionsViewed: 'onVendorTransactionsViewed',
onSalesByItemViewed: 'onSalesByItemViewed',
onPurchasesByItemViewed: 'onPurchasesByItemViewed',
},
};

View File

@@ -1,6 +0,0 @@
export class ModelEntityNotFound extends Error {
constructor(entityId, message?) {
message = message || `Entity with id ${entityId} does not exist`;
super(message);
}
}

View File

@@ -1,24 +0,0 @@
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpStatus,
} from '@nestjs/common';
import { Response } from 'express';
import { ServiceError } from '@/modules/Items/ServiceError';
@Catch(ServiceError)
export class ServiceErrorFilter implements ExceptionFilter {
catch(exception: ServiceError, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
errorType: exception.errorType,
message: exception.message,
payload: exception.payload,
});
}
}

View File

@@ -1,70 +0,0 @@
import {
CallHandler,
ExecutionContext,
Inject,
mixin,
NestInterceptor,
Optional,
Type,
} from '@nestjs/common';
import * as multer from 'multer';
import { Observable } from 'rxjs';
import { MULTER_MODULE_OPTIONS } from '../constants/files.constants';
import { transformException } from '../constants/multer.utils';
import { MulterModuleOptions } from '@nestjs/platform-express';
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface';
type MulterInstance = any;
/**
* @param {string} fieldName
* @param {Function|MulterOptions} localOptions - Function that receives controller instance or MulterOptions object
*/
export function FileInterceptor(
fieldName: string,
localOptions?: ((instance: any) => MulterOptions) | MulterOptions,
): Type<NestInterceptor> {
class MixinInterceptor implements NestInterceptor {
protected multer: MulterInstance;
constructor(
@Optional()
@Inject(MULTER_MODULE_OPTIONS)
options: (() => MulterModuleOptions | MulterModuleOptions) = () => ({}),
) {
const resolvedOptions = typeof localOptions === 'function'
? localOptions(this)
: localOptions;
this.multer = (multer as any)({
...(typeof options === 'function' ? options() : options),
...resolvedOptions,
});
}
async intercept(
context: ExecutionContext,
next: CallHandler,
): Promise<Observable<any>> {
const ctx = context.switchToHttp();
await new Promise<void>((resolve, reject) =>
this.multer.single(fieldName)(
ctx.getRequest(),
ctx.getResponse(),
(err: any) => {
if (err) {
const error = transformException(err);
return reject(error);
}
resolve();
},
),
);
return next.handle();
}
}
const Interceptor = mixin(MixinInterceptor);
return Interceptor;
}

View File

@@ -1,78 +0,0 @@
import {
type ExecutionContext,
Injectable,
type NestInterceptor,
type CallHandler,
Optional,
} from '@nestjs/common';
import { type Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export function camelToSnake<T = any>(value: T) {
if (value === null || value === undefined) {
return value;
}
if (Array.isArray(value)) {
return value.map(camelToSnake);
}
if (typeof value === 'object' && !(value instanceof Date)) {
return Object.fromEntries(
Object.entries(value).map(([key, value]) => [
key
.split(/(?=[A-Z])/)
.join('_')
.toLowerCase(),
camelToSnake(value),
]),
);
}
return value;
}
export function snakeToCamel<T = any>(value: T) {
if (value === null || value === undefined) {
return value;
}
if (Array.isArray(value)) {
return value.map(snakeToCamel);
}
const impl = (str: string) => {
const converted = str.replace(/([-_]\w)/g, (group) =>
group[1].toUpperCase(),
);
return converted[0].toLowerCase() + converted.slice(1);
};
if (typeof value === 'object' && !(value instanceof Date)) {
return Object.fromEntries(
Object.entries(value).map(([key, value]) => [
impl(key),
snakeToCamel(value),
]),
);
}
return value;
}
export const DEFAULT_STRATEGY = {
in: snakeToCamel,
out: camelToSnake,
};
@Injectable()
export class SerializeInterceptor implements NestInterceptor<any, any> {
constructor(@Optional() readonly strategy = DEFAULT_STRATEGY) {}
intercept(
context: ExecutionContext,
next: CallHandler<any>,
): Observable<any> {
const request = context.switchToHttp().getRequest();
request.body = this.strategy.in(request.body);
// handle returns stream..
return next.handle().pipe(map(this.strategy.out));
}
}

View File

@@ -1,29 +0,0 @@
import {
PipeTransform,
Injectable,
ArgumentMetadata,
BadRequestException,
} from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';
@Injectable()
export class ValidationPipe implements PipeTransform<any> {
async transform(value: any, { metatype }: ArgumentMetadata) {
if (!metatype || !this.toValidate(metatype)) {
return value;
}
const object = plainToInstance(metatype, value);
const errors = await validate(object);
if (errors.length > 0) {
throw new BadRequestException(errors);
}
return value;
}
private toValidate(metatype: Function): boolean {
const types: Function[] = [String, Boolean, Number, Array, Object];
return !types.includes(metatype);
}
}

View File

@@ -1,20 +0,0 @@
import {
PipeTransform,
ArgumentMetadata,
BadRequestException,
} from '@nestjs/common';
import { ZodSchema } from 'zod';
export class ZodValidationPipe implements PipeTransform {
constructor(private schema: ZodSchema) {}
transform(value: unknown, metadata: ArgumentMetadata) {
try {
const parsedValue = this.schema.parse(value);
return parsedValue;
} catch (error) {
console.log(error);
throw new BadRequestException(error.errors);
}
}
}

View File

@@ -1,260 +0,0 @@
// import hashObject from 'object-hash';
// import { EntityRepository } from './EntityRepository';
// export class CachableRepository extends EntityRepository {
// repositoryName: string;
// cache: any;
// i18n: any;
// /**
// * Constructor method.
// * @param {Knex} knex
// * @param {Cache} cache
// */
// constructor(knex, cache, i18n) {
// super(knex);
// this.cache = cache;
// this.i18n = i18n;
// this.repositoryName = this.constructor.name;
// }
// getByCache(key, callback) {
// return callback();
// }
// /**
// * Retrieve the cache key of the method name and arguments.
// * @param {string} method
// * @param {...any} args
// * @return {string}
// */
// getCacheKey(method, ...args) {
// const hashArgs = hashObject({ ...args });
// const repositoryName = this.repositoryName;
// return `${repositoryName}-${method}-${hashArgs}`;
// }
// /**
// * Retrieve all entries with specified relations.
// * @param withRelations
// */
// all(withRelations?, trx?) {
// const cacheKey = this.getCacheKey('all', withRelations);
// return this.getByCache(cacheKey, () => {
// return super.all(withRelations, trx);
// });
// }
// /**
// * Finds list of entities with specified attributes
// * @param {Object} attributeValues - values to filter retrieved entities by
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve.
// * @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
// */
// find(attributeValues = {}, withRelations?) {
// const cacheKey = this.getCacheKey('find', attributeValues, withRelations);
// return this.getByCache(cacheKey, () => {
// return super.find(attributeValues, withRelations);
// });
// }
// /**
// * Finds list of entities with attribute values that are different from specified ones
// * @param {Object} attributeValues - values to filter retrieved entities by
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
// * @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
// */
// findWhereNot(attributeValues = {}, withRelations?) {
// const cacheKey = this.getCacheKey(
// 'findWhereNot',
// attributeValues,
// withRelations
// );
// return this.getByCache(cacheKey, () => {
// return super.findWhereNot(attributeValues, withRelations);
// });
// }
// /**
// * Finds list of entities with specified attributes (any of multiple specified values)
// * Supports both ('attrName', ['value1', 'value2]) and ({attrName: ['value1', 'value2']} formats)
// *
// * @param {string|Object} searchParam - attribute name or search criteria object
// * @param {*[]} [attributeValues] - attribute values to filter retrieved entities by
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
// * @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
// */
// findWhereIn(searchParam, attributeValues, withRelations?) {
// const cacheKey = this.getCacheKey(
// 'findWhereIn',
// attributeValues,
// withRelations
// );
// return this.getByCache(cacheKey, () => {
// return super.findWhereIn(searchParam, attributeValues, withRelations);
// });
// }
// /**
// * Finds first entity by given parameters
// *
// * @param {Object} attributeValues - values to filter retrieved entities by
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
// * @returns {Promise<Object>}
// */
// findOne(attributeValues = {}, withRelations?) {
// const cacheKey = this.getCacheKey(
// 'findOne',
// attributeValues,
// withRelations
// );
// return this.getByCache(cacheKey, () => {
// return super.findOne(attributeValues, withRelations);
// });
// }
// /**
// * Finds first entity by given parameters
// *
// * @param {string || number} id - value of id column of the entity
// * @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
// * @returns {Promise<Object>}
// */
// findOneById(id, withRelations?) {
// const cacheKey = this.getCacheKey('findOneById', id, withRelations);
// return this.getByCache(cacheKey, () => {
// return super.findOneById(id, withRelations);
// });
// }
// /**
// * Persists new entity or an array of entities.
// * This method does not recursively persist related entities, use createRecursively (to be implemented) for that.
// * Batch insert only works on PostgreSQL
// * @param {Object} entity - model instance or parameters for a new entity
// * @returns {Promise<Object>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
// */
// async create(entity, trx?) {
// const result = await super.create(entity, trx);
// // Flushes the repository cache after insert operation.
// this.flushCache();
// return result;
// }
// /**
// * Persists updated entity. If previously set fields are not present, performs an incremental update (does not remove fields unless explicitly set to null)
// *
// * @param {Object} entity - single entity instance
// * @param {Object} [trx] - knex transaction instance. If not specified, new implicit transaction will be used.
// * @returns {Promise<integer>} number of affected rows
// */
// async update(entity, whereAttributes?, trx?) {
// const result = await super.update(entity, whereAttributes, trx);
// // Flushes the repository cache after update operation.
// this.flushCache();
// return result;
// }
// /**
// * @param {Object} attributeValues - values to filter deleted entities by
// * @param {Object} [trx]
// * @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
// */
// async deleteBy(attributeValues, trx?) {
// const result = await super.deleteBy(attributeValues, trx);
// this.flushCache();
// return result;
// }
// /**
// * @param {string || number} id - value of id column of the entity
// * @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
// */
// deleteById(id: number | string, trx?) {
// const result = super.deleteById(id, trx);
// // Flushes the repository cache after insert operation.
// this.flushCache();
// return result;
// }
// /**
// *
// * @param {string|number[]} values -
// */
// async deleteWhereIn(field: string, values: string | number[]) {
// const result = await super.deleteWhereIn(field, values);
// // Flushes the repository cache after delete operation.
// this.flushCache();
// return result;
// }
// /**
// *
// * @param {string|number[]} values
// */
// async deleteWhereIdIn(values: string | number[], trx?) {
// const result = await super.deleteWhereIdIn(values, trx);
// // Flushes the repository cache after delete operation.
// this.flushCache();
// return result;
// }
// /**
// *
// * @param graph
// * @param options
// */
// async upsertGraph(graph, options) {
// const result = await super.upsertGraph(graph, options);
// // Flushes the repository cache after insert operation.
// this.flushCache();
// return result;
// }
// /**
// *
// * @param {} whereAttributes
// * @param {string} field
// * @param {number} amount
// */
// async changeNumber(whereAttributes, field: string, amount: number, trx?) {
// const result = await super.changeNumber(
// whereAttributes,
// field,
// amount,
// trx
// );
// // Flushes the repository cache after update operation.
// this.flushCache();
// return result;
// }
// /**
// * Flush repository cache.
// */
// flushCache(): void {
// this.cache.delStartWith(this.repositoryName);
// }
// }

View File

@@ -1,232 +0,0 @@
import { cloneDeep, forOwn, isString } from 'lodash';
import { ModelEntityNotFound } from '../exceptions/ModelEntityNotFound';
import { Model } from 'objection';
function applyGraphFetched(withRelations, builder) {
const relations = Array.isArray(withRelations)
? withRelations
: typeof withRelations === 'string'
? withRelations.split(',').map((relation) => relation.trim())
: [];
relations.forEach((relation) => {
builder.withGraphFetched(relation);
});
}
export class EntityRepository {
idColumn: string = 'id';
knex: any;
/**
* Retrieve the repository model binded it to knex instance.
*/
get model(): typeof Model {
throw new Error("The repository's model is not defined.");
}
/**
* Retrieve all entries with specified relations.
* @param withRelations
*/
all(withRelations?, trx?) {
const builder = this.model.query(trx);
applyGraphFetched(withRelations, builder);
return builder;
}
/**
* Finds list of entities with specified attributes
*
* @param {Object} attributeValues - values to filter retrieved entities by
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve.
* @returns {Promise<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
*/
find(attributeValues = {}, withRelations?) {
const builder = this.model.query().where(attributeValues);
applyGraphFetched(withRelations, builder);
return builder;
}
/**
* Finds list of entities with attribute values that are different from specified ones
*
* @param {Object} attributeValues - values to filter retrieved entities by
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
* @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
*/
findWhereNot(attributeValues = {}, withRelations?) {
const builder = this.model.query().whereNot(attributeValues);
applyGraphFetched(withRelations, builder);
return builder;
}
/**
* Finds list of entities with specified attributes (any of multiple specified values)
* Supports both ('attrName', ['value1', 'value2]) and ({attrName: ['value1', 'value2']} formats)
*
* @param {string|Object} searchParam - attribute name or search criteria object
* @param {*[]} [attributeValues] - attribute values to filter retrieved entities by
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
* @returns {PromiseLike<Object[]>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
*/
findWhereIn(searchParam, attributeValues, withRelations?) {
const commonBuilder = (builder) => {
applyGraphFetched(withRelations, builder);
};
if (isString(searchParam)) {
return this.model
.query()
.whereIn(searchParam, attributeValues)
.onBuild(commonBuilder);
} else {
const builder = this.model.query(this.knex).onBuild(commonBuilder);
forOwn(searchParam, (value, key) => {
if (Array.isArray(value)) {
builder.whereIn(key, value);
} else {
builder.where(key, value);
}
});
return builder;
}
}
/**
* Finds first entity by given parameters
*
* @param {Object} attributeValues - values to filter retrieved entities by
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
* @returns {Promise<Object>}
*/
async findOne(attributeValues = {}, withRelations?) {
const results = await this.find(attributeValues, withRelations);
return results[0] || null;
}
/**
* Finds first entity by given parameters
*
* @param {string || number} id - value of id column of the entity
* @param {string || string[]} [withRelations] - name of relation(s) to eagerly retrieve, as defined in model relationMappings()
* @returns {Promise<Object>}
*/
findOneById(id, withRelations?) {
return this.findOne({ [this.idColumn]: id }, withRelations);
}
/**
* Persists new entity or an array of entities.
* This method does not recursively persist related entities, use createRecursively (to be implemented) for that.
* Batch insert only works on PostgreSQL
*
* @param {Object} entity - model instance or parameters for a new entity
* @returns {Promise<Object>} - query builder. You can chain additional methods to it or call "await" or then() on it to execute
*/
create(entity, trx?) {
// Keep the input parameter immutable
const instanceDTO = cloneDeep(entity);
return this.model.query(trx).insert(instanceDTO);
}
/**
* Persists updated entity. If previously set fields are not present, performs an incremental update (does not remove fields unless explicitly set to null)
*
* @param {Object} entity - single entity instance
* @returns {Promise<integer>} number of affected rows
*/
async update(entity, whereAttributes?, trx?) {
const entityDto = cloneDeep(entity);
const identityClause = {};
if (Array.isArray(this.idColumn)) {
this.idColumn.forEach(
(idColumn) => (identityClause[idColumn] = entityDto[idColumn]),
);
} else {
identityClause[this.idColumn] = entityDto[this.idColumn];
}
const whereConditions = whereAttributes || identityClause;
const modifiedEntitiesCount = await this.model
.query(trx)
.where(whereConditions)
.update(entityDto);
if (modifiedEntitiesCount === 0) {
throw new ModelEntityNotFound(entityDto[this.idColumn]);
}
return modifiedEntitiesCount;
}
/**
*
* @param {Object} attributeValues - values to filter deleted entities by
* @param {Object} [trx]
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
*/
deleteBy(attributeValues, trx?) {
return this.model.query(trx).delete().where(attributeValues);
}
/**
* @param {string || number} id - value of id column of the entity
* @returns {Promise<integer>} Query builder. After promise is resolved, returns count of deleted rows
*/
deleteById(id: number | string, trx?) {
return this.deleteBy(
{
[this.idColumn]: id,
},
trx,
);
}
/**
* Deletes the given entries in the array on the specific field.
* @param {string} field -
* @param {number|string} values -
*/
deleteWhereIn(field: string, values: (string | number)[], trx) {
return this.model.query(trx).whereIn(field, values).delete();
}
/**
*
* @param {string|number[]} values
*/
deleteWhereIdIn(values: (string | number)[], trx?) {
return this.deleteWhereIn(this.idColumn, values, trx);
}
/**
* Arbitrary relation graphs can be upserted (insert + update + delete)
* using the upsertGraph method.
* @param graph
* @param options
*/
upsertGraph(graph, options) {
// Keep the input grpah immutable
const graphCloned = cloneDeep(graph);
return this.model.query().upsertGraph(graphCloned, options);
}
/**
*
* @param {object} whereAttributes
* @param {string} field
* @param amount
*/
changeNumber(whereAttributes, field: string, amount: number, trx) {
const changeMethod = amount > 0 ? 'increment' : 'decrement';
return this.model
.query(trx)
.where(whereAttributes)
[changeMethod](field, Math.abs(amount));
}
}

View File

@@ -1,6 +0,0 @@
// import { CachableRepository } from './CachableRepository';
import { EntityRepository } from './EntityRepository';
export class TenantRepository extends EntityRepository {
}

View File

@@ -1,2 +0,0 @@
export type Constructor = new (...args: any[]) => {};
export type GConstructor<T> = new (...args: any[]) => T;

View File

@@ -1,3 +0,0 @@
import * as moment from 'moment';
export type DateInput = moment.MomentInput;

View File

@@ -1,4 +0,0 @@
export enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}

View File

@@ -1,16 +0,0 @@
export enum Features {
WAREHOUSES = 'warehouses',
BRANCHES = 'branches',
BankSyncing = 'BankSyncing',
}
export interface IFeatureAllItem {
name: string;
isAccessible: boolean;
defaultAccessible: boolean;
}
export interface IFeatureConfiugration {
name: string;
defaultValue?: boolean;
}

View File

@@ -1,8 +0,0 @@
export const AcceptType = {
ApplicationPdf: 'application/pdf',
ApplicationJson: 'application/json',
ApplicationJsonTable: 'application/json+table',
ApplicationXlsx: 'application/xlsx',
ApplicationCsv: 'application/csv',
ApplicationTextHtml: 'application/json+html',
};

View File

@@ -1,230 +0,0 @@
export const ACCOUNT_TYPE = {
CASH: 'cash',
BANK: 'bank',
ACCOUNTS_RECEIVABLE: 'accounts-receivable',
INVENTORY: 'inventory',
OTHER_CURRENT_ASSET: 'other-current-asset',
FIXED_ASSET: 'fixed-asset',
NON_CURRENT_ASSET: 'none-current-asset',
ACCOUNTS_PAYABLE: 'accounts-payable',
CREDIT_CARD: 'credit-card',
TAX_PAYABLE: 'tax-payable',
OTHER_CURRENT_LIABILITY: 'other-current-liability',
LOGN_TERM_LIABILITY: 'long-term-liability',
NON_CURRENT_LIABILITY: 'non-current-liability',
EQUITY: 'equity',
INCOME: 'income',
OTHER_INCOME: 'other-income',
COST_OF_GOODS_SOLD: 'cost-of-goods-sold',
EXPENSE: 'expense',
OTHER_EXPENSE: 'other-expense',
};
export const ACCOUNT_PARENT_TYPE = {
CURRENT_ASSET: 'current-asset',
FIXED_ASSET: 'fixed-asset',
NON_CURRENT_ASSET: 'non-current-asset',
CURRENT_LIABILITY: 'current-liability',
LOGN_TERM_LIABILITY: 'long-term-liability',
NON_CURRENT_LIABILITY: 'non-current-liability',
EQUITY: 'equity',
EXPENSE: 'expense',
INCOME: 'income',
};
export const ACCOUNT_ROOT_TYPE = {
ASSET: 'asset',
LIABILITY: 'liability',
EQUITY: 'equity',
EXPENSE: 'expense',
INCOME: 'income',
};
export const ACCOUNT_NORMAL = {
CREDIT: 'credit',
DEBIT: 'debit',
};
export const ACCOUNT_TYPES = [
{
label: 'Cash',
key: ACCOUNT_TYPE.CASH,
normal: ACCOUNT_NORMAL.DEBIT,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
rootType: ACCOUNT_ROOT_TYPE.ASSET,
multiCurrency: true,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Bank',
key: ACCOUNT_TYPE.BANK,
normal: ACCOUNT_NORMAL.DEBIT,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
rootType: ACCOUNT_ROOT_TYPE.ASSET,
multiCurrency: true,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Accounts Receivable',
key: ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.ASSET,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Inventory',
key: ACCOUNT_TYPE.INVENTORY,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.ASSET,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Other Current Asset',
key: ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.ASSET,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_ASSET,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Fixed Asset',
key: ACCOUNT_TYPE.FIXED_ASSET,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.ASSET,
parentType: ACCOUNT_PARENT_TYPE.FIXED_ASSET,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Non-Current Asset',
key: ACCOUNT_TYPE.NON_CURRENT_ASSET,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.ASSET,
parentType: ACCOUNT_PARENT_TYPE.FIXED_ASSET,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Accounts Payable',
key: ACCOUNT_TYPE.ACCOUNTS_PAYABLE,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Credit Card',
key: ACCOUNT_TYPE.CREDIT_CARD,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
multiCurrency: true,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Tax Payable',
key: ACCOUNT_TYPE.TAX_PAYABLE,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Other Current Liability',
key: ACCOUNT_TYPE.OTHER_CURRENT_LIABILITY,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
parentType: ACCOUNT_PARENT_TYPE.CURRENT_LIABILITY,
balanceSheet: false,
incomeSheet: true,
},
{
label: 'Long Term Liability',
key: ACCOUNT_TYPE.LOGN_TERM_LIABILITY,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
parentType: ACCOUNT_PARENT_TYPE.LOGN_TERM_LIABILITY,
balanceSheet: false,
incomeSheet: true,
},
{
label: 'Non-Current Liability',
key: ACCOUNT_TYPE.NON_CURRENT_LIABILITY,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.LIABILITY,
parentType: ACCOUNT_PARENT_TYPE.NON_CURRENT_LIABILITY,
balanceSheet: false,
incomeSheet: true,
},
{
label: 'Equity',
key: ACCOUNT_TYPE.EQUITY,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.EQUITY,
parentType: ACCOUNT_PARENT_TYPE.EQUITY,
balanceSheet: true,
incomeSheet: false,
},
{
label: 'Income',
key: ACCOUNT_TYPE.INCOME,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.INCOME,
parentType: ACCOUNT_PARENT_TYPE.INCOME,
balanceSheet: false,
incomeSheet: true,
},
{
label: 'Other Income',
key: ACCOUNT_TYPE.OTHER_INCOME,
normal: ACCOUNT_NORMAL.CREDIT,
rootType: ACCOUNT_ROOT_TYPE.INCOME,
parentType: ACCOUNT_PARENT_TYPE.INCOME,
balanceSheet: false,
incomeSheet: true,
},
{
label: 'Cost of Goods Sold',
key: ACCOUNT_TYPE.COST_OF_GOODS_SOLD,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.EXPENSE,
parentType: ACCOUNT_PARENT_TYPE.EXPENSE,
balanceSheet: false,
incomeSheet: true,
},
{
label: 'Expense',
key: ACCOUNT_TYPE.EXPENSE,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.EXPENSE,
parentType: ACCOUNT_PARENT_TYPE.EXPENSE,
balanceSheet: false,
incomeSheet: true,
},
{
label: 'Other Expense',
key: ACCOUNT_TYPE.OTHER_EXPENSE,
normal: ACCOUNT_NORMAL.DEBIT,
rootType: ACCOUNT_ROOT_TYPE.EXPENSE,
parentType: ACCOUNT_PARENT_TYPE.EXPENSE,
balanceSheet: false,
incomeSheet: true,
},
];
export const getAccountsSupportsMultiCurrency = () => {
return ACCOUNT_TYPES.filter((account) => account.multiCurrency);
};

View File

@@ -1,7 +0,0 @@
export const DATATYPES_LENGTH = {
STRING: 255,
TEXT: 65535,
INT_10: 4294967295,
DECIMAL_13_3: 9999999999.999,
DECIMAL_15_5: 999999999999.999,
};

View File

@@ -1,241 +0,0 @@
// import { getTransactionsLockingSettingsSchema } from '@/api/controllers/TransactionsLocking/utils';
export const SettingsOptions = {
organization: {
name: {
type: 'string',
},
base_currency: {
type: 'string',
},
industry: {
type: 'string',
},
location: {
type: 'string',
},
fiscal_year: {
type: 'string',
},
financial_date_start: {
type: 'string',
},
language: {
type: 'string',
},
time_zone: {
type: 'string',
},
date_format: {
type: 'string',
},
accounting_basis: {
type: 'string',
},
},
manual_journals: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
},
bill_payments: {
withdrawal_account: {
type: 'number',
},
},
sales_estimates: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
customer_notes: {
type: 'string',
},
terms_conditions: {
type: 'string',
},
},
sales_receipts: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
preferred_deposit_account: {
type: 'number',
},
receipt_message: {
type: 'string',
},
terms_conditions: {
type: 'string',
},
},
sales_invoices: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
customer_notes: {
type: 'string',
},
terms_conditions: {
type: 'string',
},
},
payment_receives: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
preferred_deposit_account: {
type: 'number',
},
preferred_advance_deposit: {
type: 'number',
},
},
items: {
preferred_sell_account: {
type: 'number',
},
preferred_cost_account: {
type: 'number',
},
preferred_inventory_account: {
type: 'number',
},
},
expenses: {
preferred_payment_account: {
type: 'number',
},
},
inventory: {
cost_compute_running: {
type: 'boolean',
},
},
accounts: {
account_code_required: {
type: 'boolean',
},
account_code_unique: {
type: 'boolean',
},
},
cashflow: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
},
credit_note: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
customer_notes: {
type: 'string',
},
terms_conditions: {
type: 'string',
},
},
vendor_credit: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
},
warehouse_transfers: {
next_number: {
type: 'string',
},
number_prefix: {
type: 'string',
},
auto_increment: {
type: 'boolean',
},
},
'sms-notification': {
'sms-notification-enable.sale-invoice-details': {
type: 'boolean',
},
'sms-notification-enable.sale-invoice-reminder': {
type: 'boolean',
},
'sms-notification-enable.sale-estimate-details': {
type: 'boolean',
},
'sms-notification-enable.sale-receipt-details': {
type: 'boolean',
},
'sms-notification-enable.payment-receive-details': {
type: 'boolean',
},
'sms-notification-enable.customer-balance': {
type: 'boolean',
},
},
'transactions-locking': {
'locking-type': {
type: 'string',
},
// ...getTransactionsLockingSettingsSchema([
// 'all',
// 'sales',
// 'purchases',
// 'financial',
// ]),
},
features: {
'multi-warehouses': {
type: 'boolean',
},
'multi-branches': {
type: 'boolean',
},
},
};

View File

@@ -1,19 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('accounts', (table) => {
table.increments('id').comment('Auto-generated id');
table.string('name').index();
table.string('slug');
table.string('account_type').index();
table.integer('parent_account_id').unsigned().references('id').inTable('accounts');
table.string('code', 10).index();
table.text('description');
table.boolean('active').defaultTo(true).index();
table.integer('index').unsigned();
table.boolean('predefined').defaultTo(false).index();
table.decimal('amount', 15, 5);
table.string('currency_code', 3).index();
table.timestamps();
}).raw('ALTER TABLE `ACCOUNTS` AUTO_INCREMENT = 1000');
};
exports.down = (knex) => knex.schema.dropTableIfExists('accounts');

View File

@@ -1,19 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('items_categories', (table) => {
table.increments();
table.string('name').index();
table.text('description');
table.integer('user_id').unsigned().index();
table.integer('cost_account_id').unsigned().references('id').inTable('accounts');
table.integer('sell_account_id').unsigned().references('id').inTable('accounts');
table.integer('inventory_account_id').unsigned().references('id').inTable('accounts');
table.string('cost_method');
table.timestamps();
});
};
exports.down = (knex) => knex.schema.dropTableIfExists('items_categories');

View File

@@ -1,30 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('items', (table) => {
table.increments();
table.string('name').index();
table.string('type').index();
table.string('code');
table.boolean('sellable').index();
table.boolean('purchasable').index();
table.decimal('sell_price', 13, 3).unsigned();
table.decimal('cost_price', 13, 3).unsigned();
table.string('currency_code', 3);
table.string('picture_uri');
table.integer('cost_account_id').nullable().unsigned().references('id').inTable('accounts');
table.integer('sell_account_id').nullable().unsigned().references('id').inTable('accounts');
table.integer('inventory_account_id').unsigned().references('id').inTable('accounts');
table.text('sell_description').nullable();
table.text('purchase_description').nullable();
table.integer('quantity_on_hand');
table.boolean('landed_cost').nullable();
table.text('note').nullable();
table.boolean('active');
table.integer('category_id').unsigned().index().references('id').inTable('items_categories');
table.integer('user_id').unsigned().index();
table.timestamps();
}).raw('ALTER TABLE `ITEMS` AUTO_INCREMENT = 1000');
};
exports.down = (knex) => knex.schema.dropTableIfExists('items');

View File

@@ -1,15 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('views', (table) => {
table.increments();
table.string('name').index();
table.string('slug').index();
table.boolean('predefined');
table.string('resource_model').index();
table.boolean('favourite');
table.string('roles_logic_expression');
table.timestamps();
}).raw('ALTER TABLE `VIEWS` AUTO_INCREMENT = 1000');
};
exports.down = (knex) => knex.schema.dropTableIfExists('views');

View File

@@ -1,13 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('settings', (table) => {
table.increments();
table.integer('user_id').unsigned().index();
table.string('group').index();
table.string('type');
table.string('key').index();
table.string('value');
}).raw('ALTER TABLE `SETTINGS` AUTO_INCREMENT = 2000');
};
exports.down = (knex) => knex.schema.dropTableIfExists('settings');

View File

@@ -1,11 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('view_has_columns', (table) => {
table.increments();
table.integer('view_id').unsigned().index().references('id').inTable('views');
table.string('field_key');
table.integer('index').unsigned();
}).raw('ALTER TABLE `ITEMS_CATEGORIES` AUTO_INCREMENT = 1000');
};
exports.down = (knex) => knex.schema.dropTableIfExists('view_has_columns');

View File

@@ -1,19 +0,0 @@
exports.up = function (knex) {
return knex.schema
.createTable('view_roles', (table) => {
table.increments();
table.integer('index');
table.string('field_key').index();
table.string('comparator');
table.string('value');
table
.integer('view_id')
.unsigned()
.index()
.references('id')
.inTable('views');
})
.raw('ALTER TABLE `VIEW_ROLES` AUTO_INCREMENT = 1000');
};
exports.down = (knex) => knex.schema.dropTableIfExists('view_roles');

View File

@@ -1,54 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('contacts', table => {
table.increments();
table.string('contact_service');
table.string('contact_type');
table.decimal('balance', 13, 3).defaultTo(0);
table.string('currency_code', 3);
table.decimal('opening_balance', 13, 3).defaultTo(0);
table.date('opening_balance_at');
table.string('salutation').nullable();
table.string('first_name').nullable();
table.string('last_name').nullable();
table.string('company_name').nullable();
table.string('display_name');
table.string('email').nullable();
table.string('work_phone').nullable();
table.string('personal_phone').nullable();
table.string('website').nullable();
table.string('billing_address_1').nullable();
table.string('billing_address_2').nullable();
table.string('billing_address_city').nullable();
table.string('billing_address_country').nullable();
table.string('billing_address_email').nullable();
table.string('billing_address_postcode').nullable();
table.string('billing_address_phone').nullable();
table.string('billing_address_state').nullable(),
table.string('shipping_address_1').nullable();
table.string('shipping_address_2').nullable();
table.string('shipping_address_city').nullable();
table.string('shipping_address_country').nullable();
table.string('shipping_address_email').nullable();
table.string('shipping_address_postcode').nullable();
table.string('shipping_address_phone').nullable();
table.string('shipping_address_state').nullable();
table.text('note');
table.boolean('active').defaultTo(true);
table.timestamps();
});
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('contacts');
};

View File

@@ -1,36 +0,0 @@
exports.up = function (knex) {
return knex.schema
.createTable('accounts_transactions', (table) => {
table.increments();
table.decimal('credit', 13, 3);
table.decimal('debit', 13, 3);
table.string('transaction_type').index();
table.string('reference_type').index();
table.integer('reference_id').index();
table
.integer('account_id')
.unsigned()
.index()
.references('id')
.inTable('accounts');
table.string('contact_type').nullable().index();
table.integer('contact_id').unsigned().nullable().index();
table.string('transaction_number').nullable().index();
table.string('reference_number').nullable().index();
table.integer('item_id').unsigned().nullable().index();
table.integer('item_quantity').unsigned().nullable().index(),
table.string('note');
table.integer('user_id').unsigned().index();
table.integer('index_group').unsigned().index();
table.integer('index').unsigned().index();
table.date('date').index();
table.datetime('created_at').index();
})
.raw('ALTER TABLE `ACCOUNTS_TRANSACTIONS` AUTO_INCREMENT = 1000');
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('accounts_transactions');
};

View File

@@ -1,29 +0,0 @@
exports.up = function (knex) {
return knex.schema
.createTable('expenses_transactions', (table) => {
table.increments();
table.string('currency_code', 3);
table.text('description');
table
.integer('payment_account_id')
.unsigned()
.references('id')
.inTable('accounts');
table.integer('payee_id').unsigned().references('id').inTable('contacts');
table.string('reference_no');
table.decimal('total_amount', 13, 3);
table.decimal('landed_cost_amount', 13, 3).defaultTo(0);
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
table.date('published_at').index();
table.integer('user_id').unsigned().index();
table.date('payment_date').index();
table.timestamps();
})
.raw('ALTER TABLE `EXPENSES_TRANSACTIONS` AUTO_INCREMENT = 1000');
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('expenses');
};

View File

@@ -1,21 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('manual_journals', (table) => {
table.increments();
table.string('journal_number').index();
table.string('reference').index();
table.string('journal_type').index();
table.decimal('amount', 13, 3);
table.string('currency_code', 3);
table.date('date').index();
table.string('description');
table.date('published_at').index();
table.string('attachment_file');
table.integer('user_id').unsigned().index();
table.timestamps();
}).raw('ALTER TABLE `MANUAL_JOURNALS` AUTO_INCREMENT = 1000');
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('manual_journals');
};

View File

@@ -1,17 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('manual_journals_entries', (table) => {
table.increments();
table.decimal('credit', 13, 3);
table.decimal('debit', 13, 3);
table.integer('index').unsigned();
table.integer('account_id').unsigned().index().references('id').inTable('accounts');
table.integer('contact_id').unsigned().nullable().index();
table.string('note');
table.integer('manual_journal_id').unsigned().index().references('id').inTable('manual_journals');
}).raw('ALTER TABLE `MANUAL_JOURNALS_ENTRIES` AUTO_INCREMENT = 1000');
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('manual_journals_entries');
};

View File

@@ -1,14 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('currencies', table => {
table.increments();
table.string('currency_name').index();
table.string('currency_code', 4).index();
table.string('currency_sign').index();
table.timestamps();
}).raw('ALTER TABLE `CURRENCIES` AUTO_INCREMENT = 1000');
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('currencies');
};

View File

@@ -1,14 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('exchange_rates', table => {
table.increments();
table.string('currency_code', 4).index();
table.decimal('exchange_rate');
table.date('date').index();
table.timestamps();
}).raw('ALTER TABLE `EXCHANGE_RATES` AUTO_INCREMENT = 1000');
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('exchange_rates');
};

View File

@@ -1,12 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('media', (table) => {
table.increments();
table.string('attachment_file');
table.timestamps();
});
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('media');
};

View File

@@ -1,13 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('media_links', table => {
table.increments();
table.string('model_name').index();
table.integer('media_id').unsigned().references('id').inTable('media');
table.integer('model_id').unsigned().index();
})
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('media_links');
};

View File

@@ -1,29 +0,0 @@
exports.up = function (knex) {
return knex.schema
.createTable('expense_transaction_categories', (table) => {
table.increments();
table
.integer('expense_account_id')
.unsigned()
.index()
.references('id')
.inTable('accounts');
table.integer('index').unsigned();
table.text('description');
table.decimal('amount', 13, 3);
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
table.boolean('landed_cost').defaultTo(false);
table
.integer('expense_id')
.unsigned()
.index()
.references('id')
.inTable('expenses_transactions');
table.timestamps();
})
.raw('ALTER TABLE `EXPENSE_TRANSACTION_CATEGORIES` AUTO_INCREMENT = 1000');
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('expense_transaction_categories');
};

View File

@@ -1,35 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('sales_estimates', (table) => {
table.increments();
table.decimal('amount', 13, 3);
table.string('currency_code', 3);
table
.integer('customer_id')
.unsigned()
.index()
.references('id')
.inTable('contacts');
table.date('estimate_date').index();
table.date('expiration_date').index();
table.string('reference');
table.string('estimate_number').index();
table.text('note');
table.text('terms_conditions');
table.text('send_to_email');
table.date('delivered_at').index();
table.date('approved_at').index();
table.date('rejected_at').index();
table.integer('user_id').unsigned().index();
table.integer('converted_to_invoice_id').unsigned();
table.date('converted_to_invoice_at');
table.timestamps();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('sales_estimates');
};

View File

@@ -1,22 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('sales_receipts', table => {
table.increments();
table.decimal('amount', 13, 3);
table.string('currency_code', 3);
table.integer('deposit_account_id').unsigned().index().references('id').inTable('accounts');
table.integer('customer_id').unsigned().index().references('id').inTable('contacts');
table.date('receipt_date').index();
table.string('receipt_number').index();
table.string('reference_no').index();
table.string('send_to_email');
table.text('receipt_message');
table.text('statement');
table.date('closed_at').index();
table.timestamps();
})
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('sales_receipts');
};

View File

@@ -1,34 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('sales_invoices', (table) => {
table.increments();
table
.integer('customer_id')
.unsigned()
.index()
.references('id')
.inTable('contacts');
table.date('invoice_date').index();
table.date('due_date');
table.string('invoice_no').index();
table.string('reference_no');
table.text('invoice_message');
table.text('terms_conditions');
table.decimal('balance', 13, 3);
table.decimal('payment_amount', 13, 3);
table.string('currency_code', 3);
table.decimal('credited_amount', 13, 3).defaultTo(0);
table.string('inv_lot_number').index();
table.date('delivered_at').index();
table.integer('user_id').unsigned();
table.timestamps();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('sales_invoices');
};

View File

@@ -1,30 +0,0 @@
const { knexSnakeCaseMappers } = require('objection');
exports.up = function (knex) {
return knex.schema.createTable('payment_receives', (table) => {
table.increments();
table
.integer('customer_id')
.unsigned()
.index()
.references('id')
.inTable('contacts');
table.date('payment_date').index();
table.decimal('amount', 13, 3).defaultTo(0);
table.string('currency_code', 3);
table.string('reference_no').index();
table
.integer('deposit_account_id')
.unsigned()
.references('id')
.inTable('accounts');
table.string('payment_receive_no').nullable();
table.text('statement');
table.integer('user_id').unsigned().index();
table.timestamps();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('payment_receives');
};

View File

@@ -1,23 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('payment_receives_entries', (table) => {
table.increments();
table
.integer('payment_receive_id')
.unsigned()
.index()
.references('id')
.inTable('payment_receives');
table
.integer('invoice_id')
.unsigned()
.index()
.references('id')
.inTable('sales_invoices');
table.decimal('payment_amount', 13, 3).unsigned();
table.integer('index').unsigned();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('payment_receives_entries');
};

View File

@@ -1,31 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('bills', (table) => {
table.increments();
table
.integer('vendor_id')
.unsigned()
.index()
.references('id')
.inTable('contacts');
table.string('bill_number');
table.date('bill_date').index();
table.date('due_date').index();
table.string('reference_no').index();
table.string('status').index();
table.text('note');
table.decimal('amount', 13, 3).defaultTo(0);
table.string('currency_code');
table.decimal('payment_amount', 13, 3).defaultTo(0);
table.decimal('landed_cost_amount', 13, 3).defaultTo(0);
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
table.decimal('credited_amount', 13, 3).defaultTo(0);
table.string('inv_lot_number').index();
table.date('opened_at').index();
table.integer('user_id').unsigned();
table.timestamps();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('bills');
};

View File

@@ -1,21 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('bills_payments', table => {
table.increments();
table.integer('vendor_id').unsigned().index().references('id').inTable('contacts');
table.decimal('amount', 13, 3).defaultTo(0);
table.string('currency_code');
table.integer('payment_account_id').unsigned().references('id').inTable('accounts');
table.string('payment_number').nullable().index();
table.date('payment_date').index();
table.string('payment_method');
table.string('reference');
table.integer('user_id').unsigned().index();
table.text('statement');
table.timestamps();
});
};
exports.down = function(knex) {
};

View File

@@ -1,24 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('inventory_transactions', (table) => {
table.increments('id');
table.date('date').index();
table.string('direction').index();
table
.integer('item_id')
.unsigned()
.index()
.references('id')
.inTable('items');
table.integer('quantity').unsigned();
table.decimal('rate', 13, 3).unsigned();
table.string('transaction_type').index();
table.integer('transaction_id').unsigned().index();
table.integer('entry_id').unsigned().index();
table.integer('cost_account_id').unsigned();
table.timestamps();
});
};
exports.down = function (knex) {};

View File

@@ -1,21 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('bill_located_costs', (table) => {
table.increments();
table.decimal('amount', 13, 3).unsigned();
table.integer('fromTransactionId').unsigned();
table.string('fromTransactionType');
table.integer('fromTransactionEntryId').unsigned();
table.string('allocationMethod');
table.integer('costAccountId').unsigned();
table.text('description');
table.integer('billId').unsigned();
table.timestamps();
});
};
exports.down = function (knex) {};

View File

@@ -1,11 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('bill_located_cost_entries', (table) => {
table.increments();
table.decimal('cost', 13, 3).unsigned();
table.integer('entry_id').unsigned();
table.integer('bill_located_cost_id').unsigned();
});
};
exports.down = function (knex) {};

View File

@@ -1,11 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('inventory_transaction_meta', (table) => {
table.increments('id');
table.string('transaction_number');
table.text('description');
table.integer('inventory_transaction_id').unsigned();
});
};
exports.down = function (knex) {};

View File

@@ -1,39 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('items_entries', (table) => {
table.increments();
table.string('reference_type').index();
table.string('reference_id').index();
table.integer('index').unsigned();
table
.integer('item_id')
.unsigned()
.index()
.references('id')
.inTable('items');
table.text('description');
table.integer('discount').unsigned();
table.integer('quantity').unsigned();
table.integer('rate').unsigned();
table
.integer('sell_account_id')
.unsigned()
.references('id')
.inTable('accounts');
table
.integer('cost_account_id')
.unsigned()
.references('id')
.inTable('accounts');
table.boolean('landed_cost').defaultTo(false);
table.decimal('allocated_cost_amount', 13, 3).defaultTo(0);
table.timestamps();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('items_entries');
};

View File

@@ -1,23 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('bills_payments_entries', (table) => {
table.increments();
table
.integer('bill_payment_id')
.unsigned()
.index()
.references('id')
.inTable('bills_payments');
table
.integer('bill_id')
.unsigned()
.index()
.references('id')
.inTable('bills');
table.decimal('payment_amount', 13, 3).unsigned();
table.integer('index').unsigned();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('bills_payments_entries');
};

View File

@@ -1,26 +0,0 @@
exports.up = function (knex) {
return knex.schema.createTable('inventory_cost_lot_tracker', (table) => {
table.increments();
table.date('date').index();
table.string('direction').index();
table.integer('item_id').unsigned().index();
table.integer('quantity').unsigned().index();
table.decimal('rate', 13, 3);
table.integer('remaining');
table.decimal('cost', 13, 3);
table.string('transaction_type').index();
table.integer('transaction_id').unsigned().index();
table.integer('entry_id').unsigned().index();
table.integer('cost_account_id').unsigned();
table.integer('inventory_transaction_id').unsigned().index();
table.datetime('created_at').index();
});
};
exports.down = function (knex) {
return knex.schema.dropTableIfExists('inventory_cost_lot_tracker');
};

View File

@@ -1,19 +0,0 @@
exports.up = function(knex) {
return knex.schema.createTable('inventory_adjustments', table => {
table.increments();
table.date('date').index();
table.string('type').index();
table.integer('adjustment_account_id').unsigned().references('id').inTable('accounts');
table.string('reason');
table.string('reference_no').index();
table.string('description');
table.integer('user_id').unsigned();
table.date('published_at');
table.timestamps();
});
};
exports.down = function(knex) {
return knex.schema.dropTableIfExists('inventory_adjustments');
};

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