From f3c1bfa57b5e5f6a7557be6e6d2890621fb72d88 Mon Sep 17 00:00:00 2001 From: tanshu Date: Sun, 13 May 2018 00:18:12 +0530 Subject: [PATCH] - Started using TypeScript - Using SystemJS as Module Loader - Auth and Permissions moved to Credentials.service from $rootScope - Toasts moved to Messages.service - Massive Changes - Sprint 1 done to move to Angular.io from AngularJS - Should be fully working!! :) --- .gitignore | 6 +- brewman/routes.py | 3 + .../static/app/account/account-detail.html | 20 +- .../app/account/account-list.component.ts | 7 + .../app/account/account-list.controller.js | 80 - .../app/account/account-list.controller.ts | 87 + brewman/static/app/account/account-list.html | 8 +- .../app/account/account-list.resolver.ts | 3 + .../app/account/account-type.service.ts | 3 + .../app/account/account-types.resolver.ts | 4 + .../static/app/account/account.component.ts | 7 + .../static/app/account/account.controller.js | 64 - .../static/app/account/account.controller.ts | 61 + .../static/app/account/account.resolver.ts | 4 + brewman/static/app/account/account.service.ts | 8 + .../app/account/payment-accounts.resolver.ts | 3 + .../app/account/receipt-accounts.resolver.ts | 3 + .../attendance/attendance-info.resolver.ts | 10 + .../attendance/attendance-sub.controller.js | 29 - .../attendance/attendance-sub.controller.ts | 35 + .../attendance/attendance-sub.directive.ts | 14 + .../static/app/attendance/attendance-sub.html | 12 + .../attendance/attendance-types.resolver.ts | 3 + .../attendance/attendance-types.service.ts | 3 + .../app/attendance/attendance.component.ts | 7 + .../app/attendance/attendance.controller.js | 42 - .../app/attendance/attendance.controller.ts | 34 + brewman/static/app/attendance/attendance.html | 27 +- .../app/attendance/attendance.service.ts | 3 + .../balance-sheet/balance-sheet.component.ts | 7 + .../balance-sheet/balance-sheet.controller.js | 32 - .../balance-sheet/balance-sheet.controller.ts | 24 + .../app/balance-sheet/balance-sheet.html | 8 +- .../balance-sheet/balance-sheet.resolver.ts | 11 + .../balance-sheet/balance-sheet.service.ts | 3 + brewman/static/app/base.controller.ts | 32 + .../app/cash-flow/cash-flow.component.ts | 7 + .../app/cash-flow/cash-flow.controller.js | 49 - .../app/cash-flow/cash-flow.controller.ts | 42 + brewman/static/app/cash-flow/cash-flow.html | 30 +- .../app/cash-flow/cash-flow.resolver.ts | 15 + .../static/app/cash-flow/cash-flow.service.ts | 3 + brewman/static/app/client/client-detail.html | 12 +- .../app/client/client-list.component.ts | 7 + .../app/client/client-list.controller.js | 14 - .../app/client/client-list.controller.ts | 10 + brewman/static/app/client/client-list.html | 2 +- .../static/app/client/client-list.resolver.ts | 3 + brewman/static/app/client/client.component.ts | 7 + .../static/app/client/client.controller.js | 55 - .../static/app/client/client.controller.ts | 57 + brewman/static/app/client/client.resolver.ts | 4 + brewman/static/app/client/client.service.ts | 6 + .../closing-stock/closing-stock.component.ts | 7 + .../closing-stock/closing-stock.controller.js | 32 - .../closing-stock/closing-stock.controller.ts | 24 + .../app/closing-stock/closing-stock.html | 6 +- .../closing-stock/closing-stock.resolver.ts | 11 + .../closing-stock/closing-stock.service.ts | 3 + .../static/app/common/accounting.filter.ts | 15 + brewman/static/app/common/as-date.filter.ts | 7 + brewman/static/app/common/auth.service.ts | 5 + brewman/static/app/common/clr.filter.ts | 10 + .../static/app/common/credentials.service.ts | 6 + brewman/static/app/common/debit.filter.ts | 11 + brewman/static/app/common/fadey.directive.ts | 21 + .../app/common/file-upload.directive.ts | 15 + .../static/app/common/focus-on.directive.ts | 17 + .../common/growl.service.ts} | 12 +- .../static/app/common/journal-debit.filter.ts | 15 + .../static/app/common/keypress.directive.ts | 31 + .../static/app/common/local-time.filter.ts | 51 + .../static/app/common/math-solver.service.ts | 20 + brewman/static/app/common/md.filter.ts | 8 + brewman/static/app/common/message.service.ts | 3 + .../static/app/common/ng-growl.directive.ts | 11 + .../static/app/common/on-return.directive.ts | 17 + brewman/static/app/common/percent.filter.ts | 10 + brewman/static/app/common/posted.filter.ts | 5 + .../app/common/reader-promise.service.ts | 46 + .../app/common/saveButtonText.filter.ts | 5 + .../static/app/common/tan-click.directive.ts | 27 + .../static/app/common/tokenizer.service.ts | 145 + .../common/upload-image-resizer.service.ts | 52 + brewman/static/app/common/voucher.service.ts | 44 + .../app/cost-centre/cost-centre-detail.html | 4 +- .../cost-centre/cost-centre-list.component.ts | 7 + .../cost-centre-list.controller.js | 14 - .../cost-centre-list.controller.ts | 10 + .../app/cost-centre/cost-centre-list.html | 2 +- .../cost-centre/cost-centre-list.resolver.ts | 3 + .../app/cost-centre/cost-centre.component.ts | 7 + .../app/cost-centre/cost-centre.controller.js | 34 - .../app/cost-centre/cost-centre.controller.ts | 28 + .../app/cost-centre/cost-centre.resolver.ts | 4 + .../app/cost-centre/cost-centre.service.ts | 6 + .../static/app/daybook/daybook.component.ts | 7 + .../static/app/daybook/daybook.controller.js | 40 - .../static/app/daybook/daybook.controller.ts | 36 + brewman/static/app/daybook/daybook.html | 8 +- .../static/app/daybook/daybook.resolver.ts | 12 + brewman/static/app/daybook/daybook.service.ts | 3 + .../employee-attendance-info.resolver.ts | 13 + .../employee-attendance-sub.directive.ts | 14 + .../app/employee/employee-attendance-sub.html | 12 + .../employee/employee-attendance.component.ts | 7 + .../employee-attendance.controller.js | 100 - .../employee-attendance.controller.ts | 64 + .../app/employee/employee-attendance.html | 34 +- .../employee/employee-attendance.service.ts | 3 + .../static/app/employee/employee-detail.html | 26 +- .../employee/employee-functions.component.ts | 7 + .../employee/employee-functions.controller.js | 68 - .../employee/employee-functions.controller.ts | 74 + .../app/employee/employee-functions.html | 12 +- .../app/employee/employee-list.component.ts | 7 + .../app/employee/employee-list.controller.js | 83 - .../app/employee/employee-list.controller.ts | 88 + .../static/app/employee/employee-list.html | 8 +- .../app/employee/employee-list.resolver.ts | 3 + .../static/app/employee/employee.component.ts | 7 + .../app/employee/employee.controller.js | 75 - .../app/employee/employee.controller.ts | 79 + .../static/app/employee/employee.resolver.ts | 4 + .../static/app/employee/employee.service.ts | 7 + brewman/static/app/group/group-detail.html | 8 +- .../static/app/group/group-list.component.ts | 7 + .../static/app/group/group-list.controller.js | 13 - .../static/app/group/group-list.controller.ts | 12 + brewman/static/app/group/group-list.html | 2 +- .../static/app/group/group-list.resolver.ts | 3 + brewman/static/app/group/group.component.ts | 7 + brewman/static/app/group/group.controller.js | 33 - brewman/static/app/group/group.controller.ts | 28 + brewman/static/app/group/group.resolver.ts | 4 + brewman/static/app/group/group.service.ts | 6 + brewman/static/app/home.controller.js | 7 - brewman/static/app/home/home.component.ts | 7 + brewman/static/app/home/home.controller.ts | 6 + brewman/static/app/{ => home}/home.html | 0 .../incentive/incentive-voucher.resolver.ts | 11 + .../app/incentive/incentive.component.ts | 7 + .../app/incentive/incentive.controller.ts | 126 + .../incentive.html} | 32 +- brewman/static/app/issue/batch.service.ts | 5 + .../static/app/issue/issue-grid.resolver.ts | 15 + .../static/app/issue/issue-grid.service.ts | 3 + .../app/issue/issue-modal.controller.js | 22 - .../app/issue/issue-modal.controller.ts | 26 + brewman/static/app/issue/issue-modal.html | 10 +- .../app/issue/issue-voucher.resolver.ts | 15 + brewman/static/app/issue/issue.component.ts | 7 + brewman/static/app/issue/issue.controller.js | 294 -- brewman/static/app/issue/issue.controller.ts | 283 ++ brewman/static/app/issue/issue.html | 44 +- .../app/journal/journal-modal.controller.js | 28 - .../app/journal/journal-modal.controller.ts | 32 + brewman/static/app/journal/journal-modal.html | 12 +- .../app/journal/journal-voucher.resolver.ts | 10 + .../static/app/journal/journal.component.ts | 7 + .../static/app/journal/journal.controller.js | 215 - .../static/app/journal/journal.controller.ts | 229 + brewman/static/app/journal/journal.html | 46 +- brewman/static/app/ledger/ledger.component.ts | 9 + .../static/app/ledger/ledger.controller.js | 170 - .../static/app/ledger/ledger.controller.ts | 168 + brewman/static/app/ledger/ledger.html | 28 +- brewman/static/app/ledger/ledger.resolver.ts | 13 + brewman/static/app/ledger/ledger.service.ts | 3 + brewman/static/app/login/login.component.ts | 7 + brewman/static/app/login/login.controller.js | 35 - brewman/static/app/login/login.controller.ts | 41 + brewman/static/app/login/login.html | 18 +- brewman/static/app/login/logout.component.ts | 7 + brewman/static/app/login/logout.controller.js | 15 - brewman/static/app/login/logout.controller.ts | 12 + .../net-transactions.component.ts | 7 + .../net-transactions.controller.js | 43 - .../net-transactions.controller.ts | 39 + .../net-transactions/net-transactions.html | 8 +- .../net-transactions.resolver.ts | 12 + .../net-transactions.service.ts | 3 + brewman/static/app/overlord.app.js | 466 -- brewman/static/app/overlord.app.ts | 36 + brewman/static/app/overlord.components.ts | 99 + brewman/static/app/overlord.config.ts | 40 + brewman/static/app/overlord.directive.ts | 23 + brewman/static/app/overlord.filters.ts | 26 + brewman/static/app/overlord.routes.ts | 474 ++ brewman/static/app/overlord.services.ts | 84 + .../app/payment/payment-modal.controller.js | 17 - .../app/payment/payment-modal.controller.ts | 21 + brewman/static/app/payment/payment-modal.html | 10 +- .../app/payment/payment-voucher.resolver.ts | 16 + .../static/app/payment/payment.component.ts | 7 + .../static/app/payment/payment.controller.js | 216 - .../static/app/payment/payment.controller.ts | 222 + brewman/static/app/payment/payment.html | 48 +- .../product-group/product-group-detail.html | 4 +- .../product-group-list.component.ts | 7 + .../product-group-list.controller.js | 13 - .../product-group-list.controller.ts | 10 + .../app/product-group/product-group-list.html | 2 +- .../product-group-list.resolver.ts | 3 + .../product-group/product-group.component.ts | 7 + .../product-group/product-group.controller.js | 33 - .../product-group/product-group.controller.ts | 28 + .../product-group/product-group.resolver.ts | 4 + .../product-group/product-group.service.ts | 6 + .../product-ledger.component.ts | 7 + .../product-ledger.controller.js | 61 - .../product-ledger.controller.ts | 61 + .../app/product-ledger/product-ledger.html | 36 +- .../product-ledger/product-ledger.resolver.ts | 13 + .../product-ledger/product-ledger.service.ts | 3 + .../static/app/product/product-detail.html | 32 +- .../app/product/product-list.component.ts | 7 + .../app/product/product-list.controller.js | 133 - .../app/product/product-list.controller.ts | 140 + brewman/static/app/product/product-list.html | 18 +- .../app/product/product-list.resolver.ts | 3 + .../static/app/product/product.component.ts | 7 + .../static/app/product/product.controller.js | 61 - .../static/app/product/product.controller.ts | 53 + .../static/app/product/product.resolver.ts | 4 + brewman/static/app/product/product.service.ts | 7 + .../app/profit-loss/profit-loss.component.ts | 7 + .../app/profit-loss/profit-loss.controller.js | 38 - .../app/profit-loss/profit-loss.controller.ts | 36 + .../static/app/profit-loss/profit-loss.html | 10 +- .../app/profit-loss/profit-loss.resolver.ts | 12 + .../app/profit-loss/profit-loss.service.ts | 3 + .../purchase-entries.component.ts | 7 + .../purchase-entries.controller.js | 44 - .../purchase-entries.controller.ts | 39 + .../purchase-entries/purchase-entries.html | 8 +- .../purchase-entries.resolver.ts | 12 + .../purchase-entries.service.ts | 3 + .../purchase-return-modal.controller.js | 22 - .../purchase-return-modal.controller.ts | 26 + .../purchase-return-modal.html | 10 +- .../purchase-return-voucher.resolver.ts | 10 + .../purchase-return.component.ts | 7 + .../purchase-return.controller.js | 202 - .../purchase-return.controller.ts | 220 + .../app/purchase-return/purchase-return.html | 46 +- .../app/purchase/purchase-modal.controller.js | 21 - .../app/purchase/purchase-modal.controller.ts | 25 + .../static/app/purchase/purchase-modal.html | 16 +- .../app/purchase/purchase-voucher.resolver.ts | 11 + .../static/app/purchase/purchase.component.ts | 7 + .../app/purchase/purchase.controller.js | 205 - .../app/purchase/purchase.controller.ts | 222 + brewman/static/app/purchase/purchase.html | 52 +- .../app/purchases/purchases.component.ts | 7 + .../app/purchases/purchases.controller.js | 38 - .../app/purchases/purchases.controller.ts | 34 + brewman/static/app/purchases/purchases.html | 10 +- .../app/purchases/purchases.resolver.ts | 12 + .../static/app/purchases/purchases.service.ts | 3 + .../raw-material-cost-detail.html | 8 +- .../raw-material-cost.component.ts | 7 + .../raw-material-cost.controller.js | 46 - .../raw-material-cost.controller.ts | 39 + .../raw-material-cost/raw-material-cost.html | 10 +- .../raw-material-cost.resolver.ts | 15 + .../raw-material-cost.service.ts | 3 + .../app/receipt/receipt-modal.controller.js | 17 - .../app/receipt/receipt-modal.controller.ts | 21 + brewman/static/app/receipt/receipt-modal.html | 10 +- .../app/receipt/receipt-voucher.resolver.ts | 16 + .../static/app/receipt/receipt.component.ts | 7 + .../static/app/receipt/receipt.controller.js | 215 - .../static/app/receipt/receipt.controller.ts | 222 + brewman/static/app/receipt/receipt.html | 48 +- brewman/static/app/recipe/recipe-detail.html | 46 +- .../app/recipe/recipe-list.controller.js | 124 - brewman/static/app/recipe/recipe-list.html | 12 +- .../static/app/recipe/recipe.controller.js | 117 - brewman/static/app/recipe/recipe.service.ts | 6 + .../app/reconcile/reconcile.component.ts | 7 + .../app/reconcile/reconcile.controller.js | 152 - .../app/reconcile/reconcile.controller.ts | 157 + brewman/static/app/reconcile/reconcile.html | 32 +- .../app/reconcile/reconcile.resolver.ts | 13 + .../static/app/reconcile/reconcile.service.ts | 3 + .../salary-deduction-voucher.resolver.ts | 11 + .../salary-deduction.component.ts | 7 + .../salary-deduction.controller.js | 177 - .../salary-deduction.controller.ts | 181 + .../salary-deduction/salary-deduction.html | 34 +- .../service-charge.controller.js | 123 - .../static/app/settings/lock-info.resolver.ts | 9 + .../app/settings/maintenance.resolver.ts | 9 + .../static/app/settings/settings.component.ts | 7 + .../app/settings/settings.controller.js | 181 - .../app/settings/settings.controller.ts | 194 + brewman/static/app/settings/settings.html | 60 +- .../stock-movement.component.ts | 7 + .../stock-movement.controller.js | 40 - .../stock-movement.controller.ts | 39 + .../app/stock-movement/stock-movement.html | 8 +- .../stock-movement/stock-movement.resolver.ts | 12 + .../stock-movement/stock-movement.service.ts | 3 + .../trial-balance/trial-balance.component.ts | 7 + .../trial-balance/trial-balance.controller.js | 30 - .../trial-balance/trial-balance.controller.ts | 26 + .../app/trial-balance/trial-balance.html | 6 +- .../trial-balance/trial-balance.resolver.ts | 11 + .../trial-balance/trial-balance.service.ts | 3 + .../static/app/unposted/unposted.component.ts | 7 + .../app/unposted/unposted.controller.js | 18 - .../app/unposted/unposted.controller.ts | 14 + brewman/static/app/unposted/unposted.html | 4 +- .../static/app/unposted/unposted.resolver.ts | 6 + .../static/app/unposted/unposted.service.ts | 3 + brewman/static/app/user/user-detail.html | 12 +- .../static/app/user/user-list.component.ts | 7 + .../static/app/user/user-list.controller.js | 13 - .../static/app/user/user-list.controller.ts | 10 + brewman/static/app/user/user-list.html | 2 +- brewman/static/app/user/user-list.resolver.ts | 4 + brewman/static/app/user/user.component.ts | 7 + brewman/static/app/user/user.controller.js | 33 - brewman/static/app/user/user.controller.ts | 28 + brewman/static/app/user/user.resolver.ts | 4 + brewman/static/app/user/user.service.ts | 7 + brewman/static/base.html | 119 +- brewman/static/js/jquery-2.1.3.min.js | 4 - brewman/static/js/jquery-2.1.3.min.map | 1 - brewman/static/js/moment.js | 4301 ----------------- brewman/static/js/mousetrap.min.js | 11 - brewman/static/js/showdown.min.js | 62 - brewman/static/package.json | 31 + brewman/static/scripts/angular_directive.js | 157 - brewman/static/scripts/angular_filter.js | 136 - brewman/static/scripts/angular_service.js | 473 -- brewman/static/systemjs.config.js | 70 + brewman/static/template/modal/confirm.html | 10 +- brewman/static/template/modal/image.html | 2 +- brewman/static/tsconfig.json | 20 + brewman/views/__init__.py | 14 + 342 files changed, 6810 insertions(+), 10313 deletions(-) create mode 100644 brewman/static/app/account/account-list.component.ts delete mode 100644 brewman/static/app/account/account-list.controller.js create mode 100644 brewman/static/app/account/account-list.controller.ts create mode 100644 brewman/static/app/account/account-list.resolver.ts create mode 100644 brewman/static/app/account/account-type.service.ts create mode 100644 brewman/static/app/account/account-types.resolver.ts create mode 100644 brewman/static/app/account/account.component.ts delete mode 100644 brewman/static/app/account/account.controller.js create mode 100644 brewman/static/app/account/account.controller.ts create mode 100644 brewman/static/app/account/account.resolver.ts create mode 100644 brewman/static/app/account/account.service.ts create mode 100644 brewman/static/app/account/payment-accounts.resolver.ts create mode 100644 brewman/static/app/account/receipt-accounts.resolver.ts create mode 100644 brewman/static/app/attendance/attendance-info.resolver.ts delete mode 100644 brewman/static/app/attendance/attendance-sub.controller.js create mode 100644 brewman/static/app/attendance/attendance-sub.controller.ts create mode 100644 brewman/static/app/attendance/attendance-sub.directive.ts create mode 100644 brewman/static/app/attendance/attendance-sub.html create mode 100644 brewman/static/app/attendance/attendance-types.resolver.ts create mode 100644 brewman/static/app/attendance/attendance-types.service.ts create mode 100644 brewman/static/app/attendance/attendance.component.ts delete mode 100644 brewman/static/app/attendance/attendance.controller.js create mode 100644 brewman/static/app/attendance/attendance.controller.ts create mode 100644 brewman/static/app/attendance/attendance.service.ts create mode 100644 brewman/static/app/balance-sheet/balance-sheet.component.ts delete mode 100644 brewman/static/app/balance-sheet/balance-sheet.controller.js create mode 100644 brewman/static/app/balance-sheet/balance-sheet.controller.ts create mode 100644 brewman/static/app/balance-sheet/balance-sheet.resolver.ts create mode 100644 brewman/static/app/balance-sheet/balance-sheet.service.ts create mode 100644 brewman/static/app/base.controller.ts create mode 100644 brewman/static/app/cash-flow/cash-flow.component.ts delete mode 100644 brewman/static/app/cash-flow/cash-flow.controller.js create mode 100644 brewman/static/app/cash-flow/cash-flow.controller.ts create mode 100644 brewman/static/app/cash-flow/cash-flow.resolver.ts create mode 100644 brewman/static/app/cash-flow/cash-flow.service.ts create mode 100644 brewman/static/app/client/client-list.component.ts delete mode 100644 brewman/static/app/client/client-list.controller.js create mode 100644 brewman/static/app/client/client-list.controller.ts create mode 100644 brewman/static/app/client/client-list.resolver.ts create mode 100644 brewman/static/app/client/client.component.ts delete mode 100644 brewman/static/app/client/client.controller.js create mode 100644 brewman/static/app/client/client.controller.ts create mode 100644 brewman/static/app/client/client.resolver.ts create mode 100644 brewman/static/app/client/client.service.ts create mode 100644 brewman/static/app/closing-stock/closing-stock.component.ts delete mode 100644 brewman/static/app/closing-stock/closing-stock.controller.js create mode 100644 brewman/static/app/closing-stock/closing-stock.controller.ts create mode 100644 brewman/static/app/closing-stock/closing-stock.resolver.ts create mode 100644 brewman/static/app/closing-stock/closing-stock.service.ts create mode 100644 brewman/static/app/common/accounting.filter.ts create mode 100644 brewman/static/app/common/as-date.filter.ts create mode 100644 brewman/static/app/common/auth.service.ts create mode 100644 brewman/static/app/common/clr.filter.ts create mode 100644 brewman/static/app/common/credentials.service.ts create mode 100644 brewman/static/app/common/debit.filter.ts create mode 100644 brewman/static/app/common/fadey.directive.ts create mode 100644 brewman/static/app/common/file-upload.directive.ts create mode 100644 brewman/static/app/common/focus-on.directive.ts rename brewman/static/{scripts/growl-service.js => app/common/growl.service.ts} (86%) create mode 100644 brewman/static/app/common/journal-debit.filter.ts create mode 100644 brewman/static/app/common/keypress.directive.ts create mode 100644 brewman/static/app/common/local-time.filter.ts create mode 100644 brewman/static/app/common/math-solver.service.ts create mode 100644 brewman/static/app/common/md.filter.ts create mode 100644 brewman/static/app/common/message.service.ts create mode 100644 brewman/static/app/common/ng-growl.directive.ts create mode 100644 brewman/static/app/common/on-return.directive.ts create mode 100644 brewman/static/app/common/percent.filter.ts create mode 100644 brewman/static/app/common/posted.filter.ts create mode 100644 brewman/static/app/common/reader-promise.service.ts create mode 100644 brewman/static/app/common/saveButtonText.filter.ts create mode 100644 brewman/static/app/common/tan-click.directive.ts create mode 100644 brewman/static/app/common/tokenizer.service.ts create mode 100644 brewman/static/app/common/upload-image-resizer.service.ts create mode 100644 brewman/static/app/common/voucher.service.ts create mode 100644 brewman/static/app/cost-centre/cost-centre-list.component.ts delete mode 100644 brewman/static/app/cost-centre/cost-centre-list.controller.js create mode 100644 brewman/static/app/cost-centre/cost-centre-list.controller.ts create mode 100644 brewman/static/app/cost-centre/cost-centre-list.resolver.ts create mode 100644 brewman/static/app/cost-centre/cost-centre.component.ts delete mode 100644 brewman/static/app/cost-centre/cost-centre.controller.js create mode 100644 brewman/static/app/cost-centre/cost-centre.controller.ts create mode 100644 brewman/static/app/cost-centre/cost-centre.resolver.ts create mode 100644 brewman/static/app/cost-centre/cost-centre.service.ts create mode 100644 brewman/static/app/daybook/daybook.component.ts delete mode 100644 brewman/static/app/daybook/daybook.controller.js create mode 100644 brewman/static/app/daybook/daybook.controller.ts create mode 100644 brewman/static/app/daybook/daybook.resolver.ts create mode 100644 brewman/static/app/daybook/daybook.service.ts create mode 100644 brewman/static/app/employee/employee-attendance-info.resolver.ts create mode 100644 brewman/static/app/employee/employee-attendance-sub.directive.ts create mode 100644 brewman/static/app/employee/employee-attendance-sub.html create mode 100644 brewman/static/app/employee/employee-attendance.component.ts delete mode 100644 brewman/static/app/employee/employee-attendance.controller.js create mode 100644 brewman/static/app/employee/employee-attendance.controller.ts create mode 100644 brewman/static/app/employee/employee-attendance.service.ts create mode 100644 brewman/static/app/employee/employee-functions.component.ts delete mode 100644 brewman/static/app/employee/employee-functions.controller.js create mode 100644 brewman/static/app/employee/employee-functions.controller.ts create mode 100644 brewman/static/app/employee/employee-list.component.ts delete mode 100644 brewman/static/app/employee/employee-list.controller.js create mode 100644 brewman/static/app/employee/employee-list.controller.ts create mode 100644 brewman/static/app/employee/employee-list.resolver.ts create mode 100644 brewman/static/app/employee/employee.component.ts delete mode 100644 brewman/static/app/employee/employee.controller.js create mode 100644 brewman/static/app/employee/employee.controller.ts create mode 100644 brewman/static/app/employee/employee.resolver.ts create mode 100644 brewman/static/app/employee/employee.service.ts create mode 100644 brewman/static/app/group/group-list.component.ts delete mode 100644 brewman/static/app/group/group-list.controller.js create mode 100644 brewman/static/app/group/group-list.controller.ts create mode 100644 brewman/static/app/group/group-list.resolver.ts create mode 100644 brewman/static/app/group/group.component.ts delete mode 100644 brewman/static/app/group/group.controller.js create mode 100644 brewman/static/app/group/group.controller.ts create mode 100644 brewman/static/app/group/group.resolver.ts create mode 100644 brewman/static/app/group/group.service.ts delete mode 100644 brewman/static/app/home.controller.js create mode 100644 brewman/static/app/home/home.component.ts create mode 100644 brewman/static/app/home/home.controller.ts rename brewman/static/app/{ => home}/home.html (100%) create mode 100644 brewman/static/app/incentive/incentive-voucher.resolver.ts create mode 100644 brewman/static/app/incentive/incentive.component.ts create mode 100644 brewman/static/app/incentive/incentive.controller.ts rename brewman/static/app/{employee/employee-service-charge.html => incentive/incentive.html} (60%) create mode 100644 brewman/static/app/issue/batch.service.ts create mode 100644 brewman/static/app/issue/issue-grid.resolver.ts create mode 100644 brewman/static/app/issue/issue-grid.service.ts delete mode 100644 brewman/static/app/issue/issue-modal.controller.js create mode 100644 brewman/static/app/issue/issue-modal.controller.ts create mode 100644 brewman/static/app/issue/issue-voucher.resolver.ts create mode 100644 brewman/static/app/issue/issue.component.ts delete mode 100644 brewman/static/app/issue/issue.controller.js create mode 100644 brewman/static/app/issue/issue.controller.ts delete mode 100644 brewman/static/app/journal/journal-modal.controller.js create mode 100644 brewman/static/app/journal/journal-modal.controller.ts create mode 100644 brewman/static/app/journal/journal-voucher.resolver.ts create mode 100644 brewman/static/app/journal/journal.component.ts delete mode 100644 brewman/static/app/journal/journal.controller.js create mode 100644 brewman/static/app/journal/journal.controller.ts create mode 100644 brewman/static/app/ledger/ledger.component.ts delete mode 100644 brewman/static/app/ledger/ledger.controller.js create mode 100644 brewman/static/app/ledger/ledger.controller.ts create mode 100644 brewman/static/app/ledger/ledger.resolver.ts create mode 100644 brewman/static/app/ledger/ledger.service.ts create mode 100644 brewman/static/app/login/login.component.ts delete mode 100644 brewman/static/app/login/login.controller.js create mode 100644 brewman/static/app/login/login.controller.ts create mode 100644 brewman/static/app/login/logout.component.ts delete mode 100644 brewman/static/app/login/logout.controller.js create mode 100644 brewman/static/app/login/logout.controller.ts create mode 100644 brewman/static/app/net-transactions/net-transactions.component.ts delete mode 100644 brewman/static/app/net-transactions/net-transactions.controller.js create mode 100644 brewman/static/app/net-transactions/net-transactions.controller.ts create mode 100644 brewman/static/app/net-transactions/net-transactions.resolver.ts create mode 100644 brewman/static/app/net-transactions/net-transactions.service.ts delete mode 100644 brewman/static/app/overlord.app.js create mode 100644 brewman/static/app/overlord.app.ts create mode 100644 brewman/static/app/overlord.components.ts create mode 100644 brewman/static/app/overlord.config.ts create mode 100644 brewman/static/app/overlord.directive.ts create mode 100644 brewman/static/app/overlord.filters.ts create mode 100644 brewman/static/app/overlord.routes.ts create mode 100644 brewman/static/app/overlord.services.ts delete mode 100644 brewman/static/app/payment/payment-modal.controller.js create mode 100644 brewman/static/app/payment/payment-modal.controller.ts create mode 100644 brewman/static/app/payment/payment-voucher.resolver.ts create mode 100644 brewman/static/app/payment/payment.component.ts delete mode 100644 brewman/static/app/payment/payment.controller.js create mode 100644 brewman/static/app/payment/payment.controller.ts create mode 100644 brewman/static/app/product-group/product-group-list.component.ts delete mode 100644 brewman/static/app/product-group/product-group-list.controller.js create mode 100644 brewman/static/app/product-group/product-group-list.controller.ts create mode 100644 brewman/static/app/product-group/product-group-list.resolver.ts create mode 100644 brewman/static/app/product-group/product-group.component.ts delete mode 100644 brewman/static/app/product-group/product-group.controller.js create mode 100644 brewman/static/app/product-group/product-group.controller.ts create mode 100644 brewman/static/app/product-group/product-group.resolver.ts create mode 100644 brewman/static/app/product-group/product-group.service.ts create mode 100644 brewman/static/app/product-ledger/product-ledger.component.ts delete mode 100644 brewman/static/app/product-ledger/product-ledger.controller.js create mode 100644 brewman/static/app/product-ledger/product-ledger.controller.ts create mode 100644 brewman/static/app/product-ledger/product-ledger.resolver.ts create mode 100644 brewman/static/app/product-ledger/product-ledger.service.ts create mode 100644 brewman/static/app/product/product-list.component.ts delete mode 100644 brewman/static/app/product/product-list.controller.js create mode 100644 brewman/static/app/product/product-list.controller.ts create mode 100644 brewman/static/app/product/product-list.resolver.ts create mode 100644 brewman/static/app/product/product.component.ts delete mode 100644 brewman/static/app/product/product.controller.js create mode 100644 brewman/static/app/product/product.controller.ts create mode 100644 brewman/static/app/product/product.resolver.ts create mode 100644 brewman/static/app/product/product.service.ts create mode 100644 brewman/static/app/profit-loss/profit-loss.component.ts delete mode 100644 brewman/static/app/profit-loss/profit-loss.controller.js create mode 100644 brewman/static/app/profit-loss/profit-loss.controller.ts create mode 100644 brewman/static/app/profit-loss/profit-loss.resolver.ts create mode 100644 brewman/static/app/profit-loss/profit-loss.service.ts create mode 100644 brewman/static/app/purchase-entries/purchase-entries.component.ts delete mode 100644 brewman/static/app/purchase-entries/purchase-entries.controller.js create mode 100644 brewman/static/app/purchase-entries/purchase-entries.controller.ts create mode 100644 brewman/static/app/purchase-entries/purchase-entries.resolver.ts create mode 100644 brewman/static/app/purchase-entries/purchase-entries.service.ts delete mode 100644 brewman/static/app/purchase-return/purchase-return-modal.controller.js create mode 100644 brewman/static/app/purchase-return/purchase-return-modal.controller.ts create mode 100644 brewman/static/app/purchase-return/purchase-return-voucher.resolver.ts create mode 100644 brewman/static/app/purchase-return/purchase-return.component.ts delete mode 100644 brewman/static/app/purchase-return/purchase-return.controller.js create mode 100644 brewman/static/app/purchase-return/purchase-return.controller.ts delete mode 100644 brewman/static/app/purchase/purchase-modal.controller.js create mode 100644 brewman/static/app/purchase/purchase-modal.controller.ts create mode 100644 brewman/static/app/purchase/purchase-voucher.resolver.ts create mode 100644 brewman/static/app/purchase/purchase.component.ts delete mode 100644 brewman/static/app/purchase/purchase.controller.js create mode 100644 brewman/static/app/purchase/purchase.controller.ts create mode 100644 brewman/static/app/purchases/purchases.component.ts delete mode 100644 brewman/static/app/purchases/purchases.controller.js create mode 100644 brewman/static/app/purchases/purchases.controller.ts create mode 100644 brewman/static/app/purchases/purchases.resolver.ts create mode 100644 brewman/static/app/purchases/purchases.service.ts create mode 100644 brewman/static/app/raw-material-cost/raw-material-cost.component.ts delete mode 100644 brewman/static/app/raw-material-cost/raw-material-cost.controller.js create mode 100644 brewman/static/app/raw-material-cost/raw-material-cost.controller.ts create mode 100644 brewman/static/app/raw-material-cost/raw-material-cost.resolver.ts create mode 100644 brewman/static/app/raw-material-cost/raw-material-cost.service.ts delete mode 100644 brewman/static/app/receipt/receipt-modal.controller.js create mode 100644 brewman/static/app/receipt/receipt-modal.controller.ts create mode 100644 brewman/static/app/receipt/receipt-voucher.resolver.ts create mode 100644 brewman/static/app/receipt/receipt.component.ts delete mode 100644 brewman/static/app/receipt/receipt.controller.js create mode 100644 brewman/static/app/receipt/receipt.controller.ts delete mode 100644 brewman/static/app/recipe/recipe-list.controller.js delete mode 100644 brewman/static/app/recipe/recipe.controller.js create mode 100644 brewman/static/app/recipe/recipe.service.ts create mode 100644 brewman/static/app/reconcile/reconcile.component.ts delete mode 100644 brewman/static/app/reconcile/reconcile.controller.js create mode 100644 brewman/static/app/reconcile/reconcile.controller.ts create mode 100644 brewman/static/app/reconcile/reconcile.resolver.ts create mode 100644 brewman/static/app/reconcile/reconcile.service.ts create mode 100644 brewman/static/app/salary-deduction/salary-deduction-voucher.resolver.ts create mode 100644 brewman/static/app/salary-deduction/salary-deduction.component.ts delete mode 100644 brewman/static/app/salary-deduction/salary-deduction.controller.js create mode 100644 brewman/static/app/salary-deduction/salary-deduction.controller.ts delete mode 100644 brewman/static/app/service-charge/service-charge.controller.js create mode 100644 brewman/static/app/settings/lock-info.resolver.ts create mode 100644 brewman/static/app/settings/maintenance.resolver.ts create mode 100644 brewman/static/app/settings/settings.component.ts delete mode 100644 brewman/static/app/settings/settings.controller.js create mode 100644 brewman/static/app/settings/settings.controller.ts create mode 100644 brewman/static/app/stock-movement/stock-movement.component.ts delete mode 100644 brewman/static/app/stock-movement/stock-movement.controller.js create mode 100644 brewman/static/app/stock-movement/stock-movement.controller.ts create mode 100644 brewman/static/app/stock-movement/stock-movement.resolver.ts create mode 100644 brewman/static/app/stock-movement/stock-movement.service.ts create mode 100644 brewman/static/app/trial-balance/trial-balance.component.ts delete mode 100644 brewman/static/app/trial-balance/trial-balance.controller.js create mode 100644 brewman/static/app/trial-balance/trial-balance.controller.ts create mode 100644 brewman/static/app/trial-balance/trial-balance.resolver.ts create mode 100644 brewman/static/app/trial-balance/trial-balance.service.ts create mode 100644 brewman/static/app/unposted/unposted.component.ts delete mode 100644 brewman/static/app/unposted/unposted.controller.js create mode 100644 brewman/static/app/unposted/unposted.controller.ts create mode 100644 brewman/static/app/unposted/unposted.resolver.ts create mode 100644 brewman/static/app/unposted/unposted.service.ts create mode 100644 brewman/static/app/user/user-list.component.ts delete mode 100644 brewman/static/app/user/user-list.controller.js create mode 100644 brewman/static/app/user/user-list.controller.ts create mode 100644 brewman/static/app/user/user-list.resolver.ts create mode 100644 brewman/static/app/user/user.component.ts delete mode 100644 brewman/static/app/user/user.controller.js create mode 100644 brewman/static/app/user/user.controller.ts create mode 100644 brewman/static/app/user/user.resolver.ts create mode 100644 brewman/static/app/user/user.service.ts delete mode 100644 brewman/static/js/jquery-2.1.3.min.js delete mode 100644 brewman/static/js/jquery-2.1.3.min.map delete mode 100644 brewman/static/js/moment.js delete mode 100644 brewman/static/js/mousetrap.min.js delete mode 100644 brewman/static/js/showdown.min.js create mode 100644 brewman/static/package.json delete mode 100644 brewman/static/scripts/angular_directive.js delete mode 100644 brewman/static/scripts/angular_filter.js delete mode 100644 brewman/static/scripts/angular_service.js create mode 100644 brewman/static/systemjs.config.js create mode 100644 brewman/static/tsconfig.json diff --git a/.gitignore b/.gitignore index bc9f961c..d088e83e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,8 @@ env .pydevproject */__pycache__/ .idea/ -*.egg-info/ \ No newline at end of file +*.egg-info/ +brewman/static/node_modules +brewman/static/app/**/*.js +brewman/static/app/**/*.map +brewman/static/package-lock.json diff --git a/brewman/routes.py b/brewman/routes.py index 70a67abb..3911cdc8 100644 --- a/brewman/routes.py +++ b/brewman/routes.py @@ -13,6 +13,7 @@ def includeme(config): config.add_static_view('partial', 'brewman:static/partial', cache_max_age=get_age(10)) config.add_static_view('template', 'brewman:static/template', cache_max_age=get_age(10)) config.add_static_view('app', 'brewman:static/app', cache_max_age=get_age(10)) + config.add_static_view('node_modules', 'brewman:static/node_modules', cache_max_age=get_age(10)) config.add_route('api_dashboard', '/api/Dashboard') config.add_route('dashboard', '/Dashboard') @@ -23,6 +24,8 @@ def includeme(config): config.add_route('logout', '/logout') config.add_route('home', '/') + config.add_route('tsconfig', '/tsconfig.json') + config.add_route('systemjs', '/systemjs.config.js') config.add_route('api_account_type_list', '/api/AccountTypes') diff --git a/brewman/static/app/account/account-detail.html b/brewman/static/app/account/account-detail.html index f4712eeb..d310f408 100644 --- a/brewman/static/app/account/account-detail.html +++ b/brewman/static/app/account/account-detail.html @@ -5,34 +5,34 @@
- +
- +
- +
@@ -40,15 +40,15 @@
- +
- - + +
diff --git a/brewman/static/app/account/account-list.component.ts b/brewman/static/app/account/account-list.component.ts new file mode 100644 index 00000000..1a1e6b80 --- /dev/null +++ b/brewman/static/app/account/account-list.component.ts @@ -0,0 +1,7 @@ +import {AccountListController} from './account-list.controller'; + +export const AccountListComponent = { + templateUrl: '/app/account/account-list.html', + controller: AccountListController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/account/account-list.controller.js b/brewman/static/app/account/account-list.controller.js deleted file mode 100644 index ea7a7c10..00000000 --- a/brewman/static/app/account/account-list.controller.js +++ /dev/null @@ -1,80 +0,0 @@ -angular - .module('overlord') - .controller('AccountListController', AccountListController); - -AccountListController.$inject = ['$scope', '$location', '$routeParams', 'Tokenizer', 'accounts']; -function AccountListController($scope, $location, $routeParams, Tokenizer, accounts) { - $scope.search = $routeParams.q || ''; - $scope.info = accounts; - - $scope.$watch('search', function (value) { - $scope.filterAccounts(value); - }, true); - - $scope.$on('$destroy', function () { - Tokenizer.doFilter.cache = {}; - }); - - $scope.searchInfo = { - comparator: { - 'n': {'Col': 'Name', 'Comparator': 'text'}, - 't': {'Col': 'Type', 'Comparator': 'text'}, - 'a': {'Col': 'IsActive', 'Comparator': 'boolean'}, - 'r': {'Col': 'IsReconcilable', 'Comparator': 'boolean'}, - 'c': {'Col': 'CostCentre', 'Comparator': 'text'} - }, - def: 'n', - sorter: { - 'n': 'Name', - 't': 'Type', - 'a': 'IsActive', - 'r': 'IsReconcilable', - 'c': 'CostCentre' - } - }; - $scope.filterAccounts = _.debounce(function (q) { - if (q !== $scope._search) { - $scope._search = q; - if (angular.isUndefined(q) || q === '') { - $location.path('/Accounts').search('q', null).replace(); - } else { - $location.path('/Accounts').search({'q': q}).replace(); - } - $scope.$apply(function () { - var matches = Tokenizer.parseFilterString(q, $scope.searchInfo); - $scope.accounts = Tokenizer.doFilter(q, $scope.info, matches); - - }); - } - }, 350); - - $scope.selected = -1; - $scope.setSelected = function (index) { - $scope.selected = Math.min(Math.max(0, index), $scope.accounts.length - 1); - }; - $scope.shortcuts = { - 'up': function (e) { - if ($scope.selected > 0) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected - 1), $scope.accounts.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - }, - 'down': function (e) { - if ($scope.selected < $scope.accounts.length - 1) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected + 1), $scope.accounts.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - } - }; -}; - -AccountListResolver.$inject = ['Account']; -function AccountListResolver(Account) { - return Account.query({}).$promise; -} diff --git a/brewman/static/app/account/account-list.controller.ts b/brewman/static/app/account/account-list.controller.ts new file mode 100644 index 00000000..c90303ec --- /dev/null +++ b/brewman/static/app/account/account-list.controller.ts @@ -0,0 +1,87 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import * as $ from 'jquery'; +import 'jqScrollIntoView'; + +export class AccountListController { + static $inject = ['$scope', '$location', '$routeParams', 'Tokenizer']; + search: any; + info: any; + searchInfo: any; + filterAccounts: any; + selected: any; + shortcuts: any; + accounts: any; + + constructor(public $scope, public $location, public $routeParams, public Tokenizer) { + this.accounts = $scope.$parent.res.accounts; + this.search = $routeParams.q || ''; + this.info = this.accounts; + + $scope.$watch('vm.search', (value) => { + this.filterAccounts(value); + }, true); + + $scope.$on('$destroy', () => { + this.Tokenizer.doFilter.cache = {}; + }); + this.searchInfo = { + comparator: { + 'n': {'Col': 'Name', 'Comparator': 'text'}, + 't': {'Col': 'Type', 'Comparator': 'text'}, + 'a': {'Col': 'IsActive', 'Comparator': 'boolean'}, + 'r': {'Col': 'IsReconcilable', 'Comparator': 'boolean'}, + 'c': {'Col': 'CostCentre', 'Comparator': 'text'} + }, + def: 'n', + sorter: { + 'n': 'Name', + 't': 'Type', + 'a': 'IsActive', + 'r': 'IsReconcilable', + 'c': 'CostCentre' + } + }; + this.filterAccounts = _.debounce((q) => { + if (q !== $scope._search) { + $scope._search = q; + if (angular.isUndefined(q) || q === '') { + this.$location.path('/Accounts').search('q', null).replace(); + } else { + this.$location.path('/Accounts').search({'q': q}).replace(); + } + $scope.$apply(() => { + let matches = Tokenizer.parseFilterString(q, this.searchInfo); + this.accounts = Tokenizer.doFilter(q, this.info, matches); + + }); + } + }, 350); + + this.selected = -1; + this.shortcuts = { + 'up': (e) => { + if (this.selected > 0) { + this.$scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected - 1), this.accounts.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + }, + 'down': (e) => { + if (this.selected < this.accounts.length - 1) { + this.$scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected + 1), this.accounts.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + } + }; + } + + setSelected(index) { + this.selected = Math.min(Math.max(0, index), this.accounts.length - 1); + } +} diff --git a/brewman/static/app/account/account-list.html b/brewman/static/app/account/account-list.html index ff54b857..22d810e3 100644 --- a/brewman/static/app/account/account-list.html +++ b/brewman/static/app/account/account-list.html @@ -3,7 +3,7 @@
+ ng-model="vm.search">
Add
- +
@@ -22,8 +22,8 @@ - + diff --git a/brewman/static/app/account/account-list.resolver.ts b/brewman/static/app/account/account-list.resolver.ts new file mode 100644 index 00000000..b17bda36 --- /dev/null +++ b/brewman/static/app/account/account-list.resolver.ts @@ -0,0 +1,3 @@ +export function AccountListResolver(Account) { + return Account.query({}).$promise; +} diff --git a/brewman/static/app/account/account-type.service.ts b/brewman/static/app/account/account-type.service.ts new file mode 100644 index 00000000..6a3f37b8 --- /dev/null +++ b/brewman/static/app/account/account-type.service.ts @@ -0,0 +1,3 @@ +export function AccountType($resource) { + return $resource('/api/AccountTypes'); +} diff --git a/brewman/static/app/account/account-types.resolver.ts b/brewman/static/app/account/account-types.resolver.ts new file mode 100644 index 00000000..b3829ac7 --- /dev/null +++ b/brewman/static/app/account/account-types.resolver.ts @@ -0,0 +1,4 @@ +export function AccountTypesResolver(AccountType) { + return AccountType.query({}).$promise; +} + diff --git a/brewman/static/app/account/account.component.ts b/brewman/static/app/account/account.component.ts new file mode 100644 index 00000000..9356eb6a --- /dev/null +++ b/brewman/static/app/account/account.component.ts @@ -0,0 +1,7 @@ +import {AccountController} from './account.controller'; + +export const AccountComponent = { + templateUrl: '/app/account/account-detail.html', + controller: AccountController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/account/account.controller.js b/brewman/static/app/account/account.controller.js deleted file mode 100644 index 80c94c64..00000000 --- a/brewman/static/app/account/account.controller.js +++ /dev/null @@ -1,64 +0,0 @@ -angular - .module('overlord') - .controller('AccountController', AccountController); - -AccountController.$inject = ['$scope', '$location', '$uibModal', 'account', 'accountTypes', 'costCentres']; -function AccountController($scope, $location, $modal, account, accountTypes, costCentres) { - $scope.account = account; - - $scope.accountTypes = accountTypes; - $scope.costCentres = costCentres; - - $scope.save = function () { - $scope.account.$save(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Accounts'); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.account.$delete(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Accounts'); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Account"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - $scope.foName = true; -}; - -AccountController.resolve = { - account: ['$route', 'Account', function ($route, Account) { - var id = $route.current.params.id; - return Account.get({id: id}).$promise; - }], - accountTypes: ['AccountType', function (AccountType) { - return AccountType.query({}).$promise; - }], - costCentres: ['CostCentre', function (CostCentre) { - return CostCentre.query({}).$promise; - }] -}; diff --git a/brewman/static/app/account/account.controller.ts b/brewman/static/app/account/account.controller.ts new file mode 100644 index 00000000..64fd5145 --- /dev/null +++ b/brewman/static/app/account/account.controller.ts @@ -0,0 +1,61 @@ +export class AccountController { + static $inject = ['$scope', '$location', '$uibModal', 'Messages']; + foName: any; + account: any; + accountTypes: any; + costCentres: any; + + constructor(public $scope, public $location, public $modal, public Messages) { + this.account = $scope.$parent.res.account; + this.accountTypes = $scope.$parent.res.accountTypes; + this.costCentres = $scope.$parent.res.costCentres; + this.foName = true; + } + + save() { + this.account.$save(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Accounts'); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.account.$delete(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Accounts'); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + confirm() { + let modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Account"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } +} diff --git a/brewman/static/app/account/account.resolver.ts b/brewman/static/app/account/account.resolver.ts new file mode 100644 index 00000000..3e486d81 --- /dev/null +++ b/brewman/static/app/account/account.resolver.ts @@ -0,0 +1,4 @@ +export function AccountResolver($route, Account) { + const id = $route.current.params.id; + return Account.get({id: id}).$promise; +} diff --git a/brewman/static/app/account/account.service.ts b/brewman/static/app/account/account.service.ts new file mode 100644 index 00000000..655835e1 --- /dev/null +++ b/brewman/static/app/account/account.service.ts @@ -0,0 +1,8 @@ +export function Account($resource) { + return $resource('/api/Account/:id', + {id: '@LedgerID'}, { + query: {method: 'GET', params: {list: true}, isArray: true}, + autocomplete: {method: 'GET', params: {term: ''}, isArray: true}, + balance: {method: 'GET', params: {b: true, d: ''}} + }); +} diff --git a/brewman/static/app/account/payment-accounts.resolver.ts b/brewman/static/app/account/payment-accounts.resolver.ts new file mode 100644 index 00000000..0927b23a --- /dev/null +++ b/brewman/static/app/account/payment-accounts.resolver.ts @@ -0,0 +1,3 @@ +export function PaymentAccountsResolver(Account) { + return Account.autocomplete({term: '', type: 1}).$promise; +} diff --git a/brewman/static/app/account/receipt-accounts.resolver.ts b/brewman/static/app/account/receipt-accounts.resolver.ts new file mode 100644 index 00000000..27e21657 --- /dev/null +++ b/brewman/static/app/account/receipt-accounts.resolver.ts @@ -0,0 +1,3 @@ +export function ReceiptAccountsResolver(Account) { + return Account.autocomplete({term: '', type: 1}).$promise; +} diff --git a/brewman/static/app/attendance/attendance-info.resolver.ts b/brewman/static/app/attendance/attendance-info.resolver.ts new file mode 100644 index 00000000..0df0d09a --- /dev/null +++ b/brewman/static/app/attendance/attendance-info.resolver.ts @@ -0,0 +1,10 @@ +import * as angular from 'angular'; + +export function AttendanceInfoResolver($route, Attendance) { + const date = $route.current.params.date; + if (angular.isUndefined(date)) { + return Attendance.get({}).$promise; + } else { + return Attendance.get({date: date}).$promise; + } +} diff --git a/brewman/static/app/attendance/attendance-sub.controller.js b/brewman/static/app/attendance/attendance-sub.controller.js deleted file mode 100644 index e7e19981..00000000 --- a/brewman/static/app/attendance/attendance-sub.controller.js +++ /dev/null @@ -1,29 +0,0 @@ -angular - .module('overlord') - .controller('AttendanceSubController', AttendanceSubController); - -AttendanceSubController.$inject = ['$scope']; -function AttendanceSubController($scope) { - $scope.original = {}; - angular.copy($scope.item, $scope.original); - - $scope.isLabel = function () { - return true; - }; - - $scope.isError = function () { - return $scope.item.Worked === 'Error'; - }; - - $scope.isGood = function () { - return $scope.item.Worked === true; - }; - - $scope.isBad = function () { - return $scope.item.Worked === false; - }; - - $scope.isDirty = function () { - return !angular.equals($scope.original, $scope.item); - }; -} diff --git a/brewman/static/app/attendance/attendance-sub.controller.ts b/brewman/static/app/attendance/attendance-sub.controller.ts new file mode 100644 index 00000000..f3aec9a9 --- /dev/null +++ b/brewman/static/app/attendance/attendance-sub.controller.ts @@ -0,0 +1,35 @@ +import * as angular from 'angular'; + +export class AttendanceSubController { + static $inject = ['$scope']; + item: any; + original: any; + attendanceTypes: any; + + constructor(public $scope) { + this.attendanceTypes = $scope.attendanceTypes; + this.item = $scope.item; + this.original = {}; + angular.copy(this.item, this.original); + } + + isLabel() { + return true; + } + + isError() { + return this.item.Worked === 'Error'; + } + + isGood() { + return this.item.Worked === true; + } + + isBad() { + return this.item.Worked === false; + } + + isDirty() { + return !angular.equals(this.original, this.item); + } +} diff --git a/brewman/static/app/attendance/attendance-sub.directive.ts b/brewman/static/app/attendance/attendance-sub.directive.ts new file mode 100644 index 00000000..a0b01bc8 --- /dev/null +++ b/brewman/static/app/attendance/attendance-sub.directive.ts @@ -0,0 +1,14 @@ +import {AttendanceSubController} from './attendance-sub.controller'; + +export function AttendanceSubDirective() { + return { + scope: { + item: '=attendanceSub', + attendanceTypes: '=attendanceTypes' + }, + restrict: 'A', + templateUrl: '/app/attendance/attendance-sub.html', + controller: AttendanceSubController, + controllerAs: 'vmSub', + }; +} diff --git a/brewman/static/app/attendance/attendance-sub.html b/brewman/static/app/attendance/attendance-sub.html new file mode 100644 index 00000000..fda3d8aa --- /dev/null +++ b/brewman/static/app/attendance/attendance-sub.html @@ -0,0 +1,12 @@ + + + + + + diff --git a/brewman/static/app/attendance/attendance-types.resolver.ts b/brewman/static/app/attendance/attendance-types.resolver.ts new file mode 100644 index 00000000..3dd4c02d --- /dev/null +++ b/brewman/static/app/attendance/attendance-types.resolver.ts @@ -0,0 +1,3 @@ +export function AttendanceTypesResolver(AttendanceTypes) { + return AttendanceTypes.query({}).$promise; +} diff --git a/brewman/static/app/attendance/attendance-types.service.ts b/brewman/static/app/attendance/attendance-types.service.ts new file mode 100644 index 00000000..f19542fa --- /dev/null +++ b/brewman/static/app/attendance/attendance-types.service.ts @@ -0,0 +1,3 @@ +export function AttendanceTypes($resource) { + return $resource('/api/AttendanceTypes'); +} diff --git a/brewman/static/app/attendance/attendance.component.ts b/brewman/static/app/attendance/attendance.component.ts new file mode 100644 index 00000000..38763032 --- /dev/null +++ b/brewman/static/app/attendance/attendance.component.ts @@ -0,0 +1,7 @@ +import {AttendanceController} from './attendance.controller'; + +export const AttendanceComponent = { + templateUrl: '/app/attendance/attendance.html', + controller: AttendanceController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/attendance/attendance.controller.js b/brewman/static/app/attendance/attendance.controller.js deleted file mode 100644 index 0c85f383..00000000 --- a/brewman/static/app/attendance/attendance.controller.js +++ /dev/null @@ -1,42 +0,0 @@ -angular - .module('overlord') - .controller('AttendanceController', AttendanceController); - -AttendanceController.$inject = ['$scope', '$location', 'asDateFilter', 'Attendance', 'attendanceTypes', 'info', 'uibDateParser']; -function AttendanceController($scope, $location, asDate, Attendance, attendanceTypes, info, dateParser) { - var _info_Date = dateParser.parse(info.Date, "dd-MMM-yyyy"); - $scope.info_Date = function (value) { - if (arguments.length) { - $scope.info.Date = asDate(value); - _info_Date = value; - } - return _info_Date; - }; - $scope.attendanceTypes = attendanceTypes; - $scope.info = info; - $scope.show = function () { - $location.path('/Attendance/' + $scope.info.Date); - }; - $scope.save = function () { - return $scope.info.$save(function (u) { - $scope.toasts.push({Type: 'Success', Message: u.Code}); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.foDate = true; -} - -tendanceController.resolve = { - info: ['$route', 'Attendance', function ($route, Attendance) { - var date = $route.current.params.date; - if (angular.isUndefined(date)) { - return Attendance.get({}).$promise; - } else { - return Attendance.get({date: date}).$promise; - } - }], - attendanceTypes: ['AttendanceTypes', function (AttendanceTypes) { - return AttendanceTypes.query({}).$promise; - }] -}; \ No newline at end of file diff --git a/brewman/static/app/attendance/attendance.controller.ts b/brewman/static/app/attendance/attendance.controller.ts new file mode 100644 index 00000000..a8ad6525 --- /dev/null +++ b/brewman/static/app/attendance/attendance.controller.ts @@ -0,0 +1,34 @@ +export class AttendanceController { + static $inject = ['$scope', '$location', 'asDateFilter', 'Attendance', 'uibDateParser', 'Messages']; + _info_Date: any; + foDate: boolean; + attendanceTypes: any; + info: any; + + constructor(public $scope, public $location, public asDate, public Attendance, public dateParser, public Messages) { + this.attendanceTypes = $scope.$parent.res.attendanceTypes; + this.info = $scope.$parent.res.info; + this._info_Date = dateParser.parse(this.info.Date, "dd-MMM-yyyy"); + this.foDate = true; + } + + info_Date(value) { + if (arguments.length) { + this.info.Date = this.asDate(value); + this._info_Date = value; + } + return this._info_Date; + } + + show() { + this.$location.path('/Attendance/' + this.info.Date); + } + + save() { + return this.info.$save((u) => { + this.Messages.push({Type: 'Success', Message: u.Code}); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } +} diff --git a/brewman/static/app/attendance/attendance.html b/brewman/static/app/attendance/attendance.html index f7edc9e0..f720ad92 100644 --- a/brewman/static/app/attendance/attendance.html +++ b/brewman/static/app/attendance/attendance.html @@ -6,9 +6,9 @@
- + @@ -16,7 +16,7 @@
- +
Name
{{item.Name}} {{item.Type}} {{item.IsActive}}{{item.Code}} {{item.Name}}{{item.Designation}}{{item.Department}} + + {{item.Prints}} + {{item.Hours}} +
@@ -31,27 +31,14 @@ - - - - - - - +
{{item.Code}} {{item.Name}}{{item.Designation}}{{item.Department}} - - {{item.Prints}} - {{item.Hours}} -
- +
diff --git a/brewman/static/app/attendance/attendance.service.ts b/brewman/static/app/attendance/attendance.service.ts new file mode 100644 index 00000000..670158aa --- /dev/null +++ b/brewman/static/app/attendance/attendance.service.ts @@ -0,0 +1,3 @@ +export function Attendance($resource) { + return $resource('/api/Attendance/:date', {date: '@Date'}); +} \ No newline at end of file diff --git a/brewman/static/app/balance-sheet/balance-sheet.component.ts b/brewman/static/app/balance-sheet/balance-sheet.component.ts new file mode 100644 index 00000000..a1e05d13 --- /dev/null +++ b/brewman/static/app/balance-sheet/balance-sheet.component.ts @@ -0,0 +1,7 @@ +import {BalanceSheetController} from './balance-sheet.controller'; + +export const BalanceSheetComponent = { + templateUrl: '/app/balance-sheet/balance-sheet.html', + controller: BalanceSheetController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/balance-sheet/balance-sheet.controller.js b/brewman/static/app/balance-sheet/balance-sheet.controller.js deleted file mode 100644 index fc4bf110..00000000 --- a/brewman/static/app/balance-sheet/balance-sheet.controller.js +++ /dev/null @@ -1,32 +0,0 @@ -angular - .module('overlord') - .controller('BalanceSheetController', BalanceSheetController); - -BalanceSheetController.$inject = ['$scope', '$location', 'asDateFilter', 'info', 'uibDateParser']; -function BalanceSheetController($scope, $location, asDate, info, dateParser) { - var _info_Date = dateParser.parse(info.Date, "dd-MMM-yyyy"); - $scope.info_Date = function (value) { - if (arguments.length) { - $scope.info.Date = asDate(value); - _info_Date = value; - } - return _info_Date; - }; - $scope.info = info; - $scope.show = function () { - $location.path('/BalanceSheet/' + $scope.info.Date); - }; - $scope.foDate = true; -} - -BalanceSheetController.resolve = { - info: ['$route', 'BalanceSheet', function ($route, BalanceSheet) { - var date = $route.current.params.date; - - if (angular.isUndefined(date)) { - return BalanceSheet.get({}).$promise; - } else { - return BalanceSheet.get({date: date}).$promise; - } - }] -}; \ No newline at end of file diff --git a/brewman/static/app/balance-sheet/balance-sheet.controller.ts b/brewman/static/app/balance-sheet/balance-sheet.controller.ts new file mode 100644 index 00000000..dfe2c6ad --- /dev/null +++ b/brewman/static/app/balance-sheet/balance-sheet.controller.ts @@ -0,0 +1,24 @@ +export class BalanceSheetController { + static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + _info_Date: any; + foDate: boolean; + info: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.info = $scope.$parent.res.info; + this._info_Date = dateParser.parse(this.info.Date, "dd-MMM-yyyy"); + this.foDate = true; + } + + info_Date(value) { + if (arguments.length) { + this.info.Date = this.asDate(value); + this._info_Date = value; + } + return this._info_Date; + } + + show() { + this.$location.path('/BalanceSheet/' + this.info.Date); + } +} diff --git a/brewman/static/app/balance-sheet/balance-sheet.html b/brewman/static/app/balance-sheet/balance-sheet.html index 37520fc0..a42bbc8d 100644 --- a/brewman/static/app/balance-sheet/balance-sheet.html +++ b/brewman/static/app/balance-sheet/balance-sheet.html @@ -7,7 +7,7 @@
@@ -15,7 +15,7 @@
- +
@@ -29,7 +29,7 @@ - + {{item.Group}} {{item.Name}} {{item.SubAmount | currency | clr}} @@ -37,7 +37,7 @@ - + {{item.Group}} {{item.Name}} {{item.SubAmount | currency | clr}} diff --git a/brewman/static/app/balance-sheet/balance-sheet.resolver.ts b/brewman/static/app/balance-sheet/balance-sheet.resolver.ts new file mode 100644 index 00000000..30828245 --- /dev/null +++ b/brewman/static/app/balance-sheet/balance-sheet.resolver.ts @@ -0,0 +1,11 @@ +import * as angular from 'angular'; + +export function BalanceSheetResolver($route, BalanceSheet) { + const date = $route.current.params.date; + + if (angular.isUndefined(date)) { + return BalanceSheet.get({}).$promise; + } else { + return BalanceSheet.get({date: date}).$promise; + } +} diff --git a/brewman/static/app/balance-sheet/balance-sheet.service.ts b/brewman/static/app/balance-sheet/balance-sheet.service.ts new file mode 100644 index 00000000..4ca2b41f --- /dev/null +++ b/brewman/static/app/balance-sheet/balance-sheet.service.ts @@ -0,0 +1,3 @@ +export function BalanceSheet($resource) { + return $resource('/api/BalanceSheet/:date'); +} diff --git a/brewman/static/app/base.controller.ts b/brewman/static/app/base.controller.ts new file mode 100644 index 00000000..a435e38e --- /dev/null +++ b/brewman/static/app/base.controller.ts @@ -0,0 +1,32 @@ +import * as angular from 'angular'; + +export class BaseController { + static $inject = ['$rootScope', 'Auth', '$location', '$routeParams', 'Messages', 'Credentials']; + + constructor(public $rootScope, public Auth, public $location, public $routeParams, public Messages, public Credentials) { + $rootScope.$on('loginRequired', () => { + if (this.Credentials.Auth.isAuthenticated) { + this.$location.path('/'); + } else { + var came_from = this.$routeParams.came_from; + if (angular.isUndefined(came_from) && $location.path() !== '/login') { + came_from = $location.url(); + } + this.$location.path('/login').search({came_from: came_from}); + } + }); + $rootScope.$on("$routeChangeStart", (event, next, current) => { + this.Auth.get((u, putResponseHeaders) => { + this.Credentials.Auth = u; + this.Credentials.Perms = u.perms; + }); + }); + } + + clearToast(item) { + var idx = this.Messages.indexOf(item); + if (idx !== -1) { + this.Messages.splice(idx, 1); + } + } +} diff --git a/brewman/static/app/cash-flow/cash-flow.component.ts b/brewman/static/app/cash-flow/cash-flow.component.ts new file mode 100644 index 00000000..f5d8fac6 --- /dev/null +++ b/brewman/static/app/cash-flow/cash-flow.component.ts @@ -0,0 +1,7 @@ +import {CashFlowController} from './cash-flow.controller'; + +export const CashFlowComponent = { + templateUrl: '/app/cash-flow/cash-flow.html', + controller: CashFlowController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/cash-flow/cash-flow.controller.js b/brewman/static/app/cash-flow/cash-flow.controller.js deleted file mode 100644 index 89f1f986..00000000 --- a/brewman/static/app/cash-flow/cash-flow.controller.js +++ /dev/null @@ -1,49 +0,0 @@ -angular - .module('overlord') - .controller('CashFlowController', CashFlowController); - -CashFlowController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'cashFlow', 'uibDateParser']; -function CashFlowController($scope, $routeParams, $location, asDate, cashFlow, dateParser) { - var _info_StartDate = dateParser.parse(cashFlow.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(cashFlow.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = cashFlow; - $scope.show = function () { - $location.path('/CashFlow').search({StartDate: $scope.info.StartDate, FinishDate: $scope.info.FinishDate}); - }; - $scope.total = function (type) { - return $scope.info.Body[type].reduce(function (accumulator, current) { - return accumulator + current.Amount; - }, 0); - }; - $scope.foDate = true; -} - -CashFlowController.resolve = { - cashFlow: ['$route', 'CashFlow', function ($route, CashFlow) { - var id = $route.current.params.id, - startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return CashFlow.get({}).$promise; - } else if (angular.isUndefined(id)) { - return CashFlow.get({StartDate: startDate, FinishDate: finishDate}).$promise; - } else { - return CashFlow.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; diff --git a/brewman/static/app/cash-flow/cash-flow.controller.ts b/brewman/static/app/cash-flow/cash-flow.controller.ts new file mode 100644 index 00000000..cc134aec --- /dev/null +++ b/brewman/static/app/cash-flow/cash-flow.controller.ts @@ -0,0 +1,42 @@ +export class CashFlowController { + static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'uibDateParser']; + _info_StartDate: any; + _info_FinishDate: any; + cashFlow: any; + info: any; + foDate: boolean; + + constructor(public $scope, public $routeParams, public $location, public asDate, public dateParser) { + this.cashFlow = $scope.$parent.res.cashFlow; + this._info_StartDate = dateParser.parse(this.cashFlow.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.cashFlow.FinishDate, "dd-MMM-yyyy"); + this.info = this.cashFlow; + this.foDate = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/CashFlow').search({StartDate: this.info.StartDate, FinishDate: this.info.FinishDate}); + } + + total(type) { + return this.info.Body[type].reduce(function (accumulator, current) { + return accumulator + current.Amount; + }, 0); + } +} diff --git a/brewman/static/app/cash-flow/cash-flow.html b/brewman/static/app/cash-flow/cash-flow.html index ccb3fb69..d15e5e7f 100644 --- a/brewman/static/app/cash-flow/cash-flow.html +++ b/brewman/static/app/cash-flow/cash-flow.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
@@ -37,48 +37,48 @@ Total - - + +
{{item.Name}} {{item.Amount | currency | clr}} - + Cash flows from Operating activities - {{total('Operating') | currency | clr}} + {{vm.total('Operating') | currency | clr}} - + {{item.Name}} {{item.Amount | currency | clr}} - + Cash flows from Investing activities - {{total('Investing') | currency | clr}} + {{vm.total('Investing') | currency | clr}} - + {{item.Name}} {{item.Amount | currency | clr}} - + Cash flows from Financing activities - {{total('Financing') | currency | clr}} + {{vm.total('Financing') | currency | clr}} - + {{item.Name}} {{item.Amount | currency | clr}} - + {{item.Name}} {{item.Amount | currency | clr}} diff --git a/brewman/static/app/cash-flow/cash-flow.resolver.ts b/brewman/static/app/cash-flow/cash-flow.resolver.ts new file mode 100644 index 00000000..90affb4d --- /dev/null +++ b/brewman/static/app/cash-flow/cash-flow.resolver.ts @@ -0,0 +1,15 @@ +import * as angular from 'angular'; + +export function CashFlowResolver($route, CashFlow) { + const id = $route.current.params.id, + startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return CashFlow.get({}).$promise; + } else if (angular.isUndefined(id)) { + return CashFlow.get({StartDate: startDate, FinishDate: finishDate}).$promise; + } else { + return CashFlow.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/cash-flow/cash-flow.service.ts b/brewman/static/app/cash-flow/cash-flow.service.ts new file mode 100644 index 00000000..5739a971 --- /dev/null +++ b/brewman/static/app/cash-flow/cash-flow.service.ts @@ -0,0 +1,3 @@ +export function CashFlow($resource) { + return $resource('/api/CashFlow/:id'); +} diff --git a/brewman/static/app/client/client-detail.html b/brewman/static/app/client/client-detail.html index baa7abd7..5f1d9c77 100644 --- a/brewman/static/app/client/client-detail.html +++ b/brewman/static/app/client/client-detail.html @@ -5,21 +5,21 @@
- +
- +
@@ -29,14 +29,14 @@
- +
- - + +
\ No newline at end of file diff --git a/brewman/static/app/client/client-list.component.ts b/brewman/static/app/client/client-list.component.ts new file mode 100644 index 00000000..db6525a8 --- /dev/null +++ b/brewman/static/app/client/client-list.component.ts @@ -0,0 +1,7 @@ +import {ClientListController} from './client-list.controller'; + +export const ClientListComponent = { + templateUrl: '/app/client/client-list.html', + controller: ClientListController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/client/client-list.controller.js b/brewman/static/app/client/client-list.controller.js deleted file mode 100644 index cd3df5a2..00000000 --- a/brewman/static/app/client/client-list.controller.js +++ /dev/null @@ -1,14 +0,0 @@ -angular - .module('overlord') - .controller('ClientListController', ClientListController); - -ClientListController.$inject = ['$scope', 'clients']; -function ClientListController($scope, clients) { - $scope.info = clients; -} - -ClientListController.resolve = { - clients: ['Client', function (Client) { - return Client.query({}).$promise; - }] -}; diff --git a/brewman/static/app/client/client-list.controller.ts b/brewman/static/app/client/client-list.controller.ts new file mode 100644 index 00000000..a656b337 --- /dev/null +++ b/brewman/static/app/client/client-list.controller.ts @@ -0,0 +1,10 @@ +export class ClientListController { + static $inject = ['$scope']; + info: any; + clients: any; + + constructor(public $scope) { + this.clients = $scope.$parent.res.clients; + this.info = this.clients; + } +} diff --git a/brewman/static/app/client/client-list.html b/brewman/static/app/client/client-list.html index ddff8899..c77d1343 100644 --- a/brewman/static/app/client/client-list.html +++ b/brewman/static/app/client/client-list.html @@ -11,7 +11,7 @@ - + {{item.Code}} {{item.Name}} {{item.Enabled}} diff --git a/brewman/static/app/client/client-list.resolver.ts b/brewman/static/app/client/client-list.resolver.ts new file mode 100644 index 00000000..48bb77dd --- /dev/null +++ b/brewman/static/app/client/client-list.resolver.ts @@ -0,0 +1,3 @@ +export function ClientListResolver(Client) { + return Client.query({}).$promise; +} diff --git a/brewman/static/app/client/client.component.ts b/brewman/static/app/client/client.component.ts new file mode 100644 index 00000000..8d6bc1b7 --- /dev/null +++ b/brewman/static/app/client/client.component.ts @@ -0,0 +1,7 @@ +import {ClientController} from './client.controller'; + +export const ClientComponent = { + templateUrl: '/app/client/client-detail.html', + controller: ClientController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/client/client.controller.js b/brewman/static/app/client/client.controller.js deleted file mode 100644 index a0c8e502..00000000 --- a/brewman/static/app/client/client.controller.js +++ /dev/null @@ -1,55 +0,0 @@ -angular - .module('overlord') - .controller('ClientController', ClientController); - -ClientController.$inject = ['$scope', '$location', '$uibModal', 'client']; -function ClientController($scope, $location, $modal, client) { - $scope.client = client; - - $scope.save = function () { - $scope.client.$save(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Clients'); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.client.$delete(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Clients'); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Client"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - $scope.foName = true; -} - -ClientController.resolve = { - client: ['$route', 'Client', function ($route, Client) { - var id = $route.current.params.id; - return Client.get({id: id}).$promise; - }] -}; diff --git a/brewman/static/app/client/client.controller.ts b/brewman/static/app/client/client.controller.ts new file mode 100644 index 00000000..fe0d081b --- /dev/null +++ b/brewman/static/app/client/client.controller.ts @@ -0,0 +1,57 @@ +export class ClientController { + static $inject = ['$scope', '$location', '$uibModal', 'Messages']; + foName: boolean; + client: any; + + constructor(public $scope, public $location, public $modal, public Messages) { + this.client = $scope.$parent.res.client; + this.foName = true; + } + + save() { + this.client.$save(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Clients'); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.client.$delete(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Clients'); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Client"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } +} diff --git a/brewman/static/app/client/client.resolver.ts b/brewman/static/app/client/client.resolver.ts new file mode 100644 index 00000000..b546ad2d --- /dev/null +++ b/brewman/static/app/client/client.resolver.ts @@ -0,0 +1,4 @@ +export function ClientResolver($route, Client) { + const id = $route.current.params.id; + return Client.get({id: id}).$promise; +} diff --git a/brewman/static/app/client/client.service.ts b/brewman/static/app/client/client.service.ts new file mode 100644 index 00000000..5aa95ecd --- /dev/null +++ b/brewman/static/app/client/client.service.ts @@ -0,0 +1,6 @@ +export function Client($resource) { + return $resource('/api/Client/:id', + {id: '@ClientID'}, { + query: {method: 'GET', params: {list: true}, isArray: true} + }); +} diff --git a/brewman/static/app/closing-stock/closing-stock.component.ts b/brewman/static/app/closing-stock/closing-stock.component.ts new file mode 100644 index 00000000..a7e2809b --- /dev/null +++ b/brewman/static/app/closing-stock/closing-stock.component.ts @@ -0,0 +1,7 @@ +import {ClosingStockController} from './closing-stock.controller'; + +export const ClosingStockComponent = { + templateUrl: '/app/closing-stock/closing-stock.html', + controller: ClosingStockController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/closing-stock/closing-stock.controller.js b/brewman/static/app/closing-stock/closing-stock.controller.js deleted file mode 100644 index 057dd056..00000000 --- a/brewman/static/app/closing-stock/closing-stock.controller.js +++ /dev/null @@ -1,32 +0,0 @@ -angular - .module('overlord') - .controller('ClosingStockController', ClosingStockController); - -ClosingStockController.$inject = ['$scope', '$location', 'asDateFilter', 'info', 'uibDateParser']; -function ClosingStockController($scope, $location, asDate, info, dateParser) { - var _info_Date = dateParser.parse(info.Date, "dd-MMM-yyyy"); - $scope.info_Date = function (value) { - if (arguments.length) { - $scope.info.Date = asDate(value); - _info_Date = value; - } - return _info_Date; - }; - $scope.info = info; - $scope.show = function () { - $location.path('/ClosingStock/' + $scope.info.Date); - }; - $scope.foDate = true; -} - -ClosingStockController.resolve = { - info: ['$route', 'ClosingStock', function ($route, ClosingStock) { - var date = $route.current.params.date; - - if (angular.isUndefined(date)) { - return ClosingStock.get({}).$promise; - } else { - return ClosingStock.get({date: date}).$promise; - } - }] -}; \ No newline at end of file diff --git a/brewman/static/app/closing-stock/closing-stock.controller.ts b/brewman/static/app/closing-stock/closing-stock.controller.ts new file mode 100644 index 00000000..93875294 --- /dev/null +++ b/brewman/static/app/closing-stock/closing-stock.controller.ts @@ -0,0 +1,24 @@ +export class ClosingStockController { + static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + _info_Date: any; + foDate: boolean; + info: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.info = $scope.$parent.res.info; + this._info_Date = dateParser.parse(this.info.Date, "dd-MMM-yyyy"); + this.foDate = true; + } + + info_Date(value) { + if (arguments.length) { + this.info.Date = this.asDate(value); + this._info_Date = value; + } + return this._info_Date; + } + + show() { + this.$location.path('/ClosingStock/' + this.info.Date); + } +} diff --git a/brewman/static/app/closing-stock/closing-stock.html b/brewman/static/app/closing-stock/closing-stock.html index d90e57aa..a0a5fc93 100644 --- a/brewman/static/app/closing-stock/closing-stock.html +++ b/brewman/static/app/closing-stock/closing-stock.html @@ -7,7 +7,7 @@
@@ -15,7 +15,7 @@
- +
@@ -29,7 +29,7 @@ - + {{item.Product}} {{item.Group}} {{item.Quantity | number:2}} diff --git a/brewman/static/app/closing-stock/closing-stock.resolver.ts b/brewman/static/app/closing-stock/closing-stock.resolver.ts new file mode 100644 index 00000000..96da5c17 --- /dev/null +++ b/brewman/static/app/closing-stock/closing-stock.resolver.ts @@ -0,0 +1,11 @@ +import * as angular from 'angular'; + +export function ClosingStockResolver($route, ClosingStock) { + const date = $route.current.params.date; + + if (angular.isUndefined(date)) { + return ClosingStock.get({}).$promise; + } else { + return ClosingStock.get({date: date}).$promise; + } +} diff --git a/brewman/static/app/closing-stock/closing-stock.service.ts b/brewman/static/app/closing-stock/closing-stock.service.ts new file mode 100644 index 00000000..b6e9e9f9 --- /dev/null +++ b/brewman/static/app/closing-stock/closing-stock.service.ts @@ -0,0 +1,3 @@ +export function ClosingStock($resource) { + return $resource('/api/ClosingStock/:date'); +} diff --git a/brewman/static/app/common/accounting.filter.ts b/brewman/static/app/common/accounting.filter.ts new file mode 100644 index 00000000..82e28b57 --- /dev/null +++ b/brewman/static/app/common/accounting.filter.ts @@ -0,0 +1,15 @@ +import * as angular from 'angular'; + +export function Accounting(currencyFilter) { + return function (amount) { + amount = currencyFilter(amount); + if (angular.isUndefined(amount) || amount === '') { + return ''; + } + if (amount.indexOf('-') !== -1) { + return amount.replace('-', '') + '\u00A0Cr'; + } else { + return amount + '\u00A0Dr'; + } + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/as-date.filter.ts b/brewman/static/app/common/as-date.filter.ts new file mode 100644 index 00000000..525961ad --- /dev/null +++ b/brewman/static/app/common/as-date.filter.ts @@ -0,0 +1,7 @@ +import * as angular from 'angular'; + +export function AsDate(dateFilter) { + return function (input) { + return angular.isDate(input) ? dateFilter(input, 'dd-MMM-yyyy') : input; + }; +} diff --git a/brewman/static/app/common/auth.service.ts b/brewman/static/app/common/auth.service.ts new file mode 100644 index 00000000..ea91e750 --- /dev/null +++ b/brewman/static/app/common/auth.service.ts @@ -0,0 +1,5 @@ +export function Auth($resource) { + return $resource('/api/Auth', {}, { + login: {method: 'GET', params: {list: true}, isArray: true} + }); +} diff --git a/brewman/static/app/common/clr.filter.ts b/brewman/static/app/common/clr.filter.ts new file mode 100644 index 00000000..616ed498 --- /dev/null +++ b/brewman/static/app/common/clr.filter.ts @@ -0,0 +1,10 @@ +import * as angular from 'angular'; + +export function Clr() { + return function (input) { + if (input === '\u20B9\u00A00.00' || input === '0.00') { + return ''; + } + return input; + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/credentials.service.ts b/brewman/static/app/common/credentials.service.ts new file mode 100644 index 00000000..7b409feb --- /dev/null +++ b/brewman/static/app/common/credentials.service.ts @@ -0,0 +1,6 @@ +export function Credentials() { + return { + Auth:{}, + Perms:[] + }; +} diff --git a/brewman/static/app/common/debit.filter.ts b/brewman/static/app/common/debit.filter.ts new file mode 100644 index 00000000..224b03a5 --- /dev/null +++ b/brewman/static/app/common/debit.filter.ts @@ -0,0 +1,11 @@ +export function Debit () { + return function (input) { + if (input === -1) { + return 'Cr'; + } else if (input === 1) { + return 'Dr'; + } else { + return ''; + } + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/fadey.directive.ts b/brewman/static/app/common/fadey.directive.ts new file mode 100644 index 00000000..3642dbac --- /dev/null +++ b/brewman/static/app/common/fadey.directive.ts @@ -0,0 +1,21 @@ +import * as $ from 'jquery'; + +export function Fadey() { + return { + restrict: 'A', + link: function (scope, element, attrs) { + const duration = 500; + element = $(element); + element.hide(); + element.fadeIn(duration); + + scope.destroy = function (complete) { + element.fadeOut(duration, function () { + if (complete) { + complete.apply(scope); + } + }); + }; + } + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/file-upload.directive.ts b/brewman/static/app/common/file-upload.directive.ts new file mode 100644 index 00000000..9b1dc9a5 --- /dev/null +++ b/brewman/static/app/common/file-upload.directive.ts @@ -0,0 +1,15 @@ +export function FileUpload() { + return { + scope: true, //create a new scope + link: function (scope, el, attrs) { + el.bind('change', function (event) { + var files = event.target.files; + //iterate files since 'multiple' may be specified on the element + for (var i = 0; i < files.length; i++) { + //emit event upward + scope.$emit("fileSelected", {file: files[i]}); + } + }); + } + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/focus-on.directive.ts b/brewman/static/app/common/focus-on.directive.ts new file mode 100644 index 00000000..50ce994a --- /dev/null +++ b/brewman/static/app/common/focus-on.directive.ts @@ -0,0 +1,17 @@ +export function FocusOn($timeout, $parse) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + scope.$watch(attrs.focusOn, function (value) { + if (value === true) { + var getter = $parse(attrs.focusOn); + var setter = getter.assign; + setter(scope, false); + $timeout(function () { + element[0].focus(); + }); + } + }); + } + }; +} \ No newline at end of file diff --git a/brewman/static/scripts/growl-service.js b/brewman/static/app/common/growl.service.ts similarity index 86% rename from brewman/static/scripts/growl-service.js rename to brewman/static/app/common/growl.service.ts index ad02e22c..a46a7f06 100644 --- a/brewman/static/scripts/growl-service.js +++ b/brewman/static/app/common/growl.service.ts @@ -1,7 +1,7 @@ -'use strict'; +import * as $ from 'jquery'; -overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($http, $compile, $timeout) { - var growl = {}; +export function Growl($http, $compile, $timeout) { + var growl:any = {}; growl.defaultOptions = { offset: { from: "top", @@ -15,7 +15,7 @@ overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($ht }; growl.show = function (element, scope, options) { - var options = jQuery.extend({}, growl.defaultOptions, options); + var options = $.extend({}, growl.defaultOptions, options); if (options.top_offset) { options.offset = { from: "top", @@ -23,7 +23,7 @@ overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($ht }; } var offsetAmount = options.offset.amount; - jQuery(".bootstrap-growl").each(function (index) { + $(".bootstrap-growl").each(function (index) { var offset = parseInt($(this).css(options.offset.from)) + $(this).outerHeight() + options.stackup_spacing; if (isNaN(offset)) { offset = 0; @@ -60,4 +60,4 @@ overlordService.factory('growl', ['$http', '$compile', '$timeout', function ($ht return element; }; return growl; -}]); +} diff --git a/brewman/static/app/common/journal-debit.filter.ts b/brewman/static/app/common/journal-debit.filter.ts new file mode 100644 index 00000000..8cdb8888 --- /dev/null +++ b/brewman/static/app/common/journal-debit.filter.ts @@ -0,0 +1,15 @@ +import * as angular from 'angular'; + +export function JournalDebit () { + return function (input, debit) { + let list = []; + if (!angular.isUndefined(input)) { + for (let i = 0, l = input.length; i < l; i++) { + if (input[i].Debit === debit) { + list.push(input[i]); + } + } + } + return list; + }; +} diff --git a/brewman/static/app/common/keypress.directive.ts b/brewman/static/app/common/keypress.directive.ts new file mode 100644 index 00000000..d4e55319 --- /dev/null +++ b/brewman/static/app/common/keypress.directive.ts @@ -0,0 +1,31 @@ +import * as Mousetrap from 'mousetrap'; +import * as _ from 'lodash'; +import 'bmMousetrap'; + +// export function Keypress() { +// return { +// link: function (scope, element, attrs) { +// const keypress = scope.$eval(attrs.keypress || '{}'); +// Mousetrap.bind(keypress); +// element.on('$destroy', function () { +// Mousetrap.unbind(keypress); +// }); +// +// } +// } +// } + +export function Keypress() { + return function (scope, element, attrs) { + const keypress = scope.$eval(attrs.keypress || '{}'); + _.forEach(keypress, function (value, key) { + Mousetrap.bind(key, value); + }); + element.on('$destroy', function () { + _.forEach(keypress, function (value, key) { + Mousetrap.unbind(key, value); + }); + }); + + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/local-time.filter.ts b/brewman/static/app/common/local-time.filter.ts new file mode 100644 index 00000000..63b9d621 --- /dev/null +++ b/brewman/static/app/common/local-time.filter.ts @@ -0,0 +1,51 @@ +import * as angular from 'angular'; + +export function LocalTime() { + const months = { + Jan: 1, + Feb: 2, + Mar: 3, + Apr: 4, + May: 5, + Jun: 6, + Jul: 7, + Aug: 8, + Sep: 9, + Oct: 10, + Nov: 11, + Dec: 12 + }; + const monthsReverse = { + 1: 'Jan', + 2: 'Feb', + 3: 'Mar', + 4: 'Apr', + 5: 'May', + 6: 'Jun', + 7: 'Jul', + 8: 'Aug', + 9: 'Sep', + 10: 'Oct', + 11: 'Nov', + 12: 'Dec' + }; + + function padNumber(input, width?: number) { + input = input + ''; + width = width || 2; + return input.length >= width ? input : new Array(width - input.length + 1).join('0') + input; + } + + return function (input) { + if (angular.isUndefined(input)) { + return ''; + } + const d = input.match(/(\w+)/g); + if (d.length !== 5) { + return input; + } + const dateInt = new Date(parseInt(d[2]), months[d[1]] - 1, parseInt(d[0]), parseInt(d[3]), parseInt(d[4])).getTime(); + const date = new Date(dateInt - (new Date().getTimezoneOffset() * 60000)); + return padNumber(date.getDate()) + '-' + monthsReverse[date.getMonth() + 1] + '-' + date.getFullYear() + ' ' + padNumber(date.getHours()) + ':' + padNumber(date.getMinutes()); + }; +} diff --git a/brewman/static/app/common/math-solver.service.ts b/brewman/static/app/common/math-solver.service.ts new file mode 100644 index 00000000..2ea31272 --- /dev/null +++ b/brewman/static/app/common/math-solver.service.ts @@ -0,0 +1,20 @@ +import * as math from 'mathjs'; + +export function MathSolver() { + return function Test(expr) { + var ans; + try { + if (typeof expr === 'number') { + ans = expr; + } else { + ans = math.eval(expr.trim().replace(',', '')); + } + } + catch (e) { + ans = Number.NaN; + } + finally { + return ans; + } + }; +} diff --git a/brewman/static/app/common/md.filter.ts b/brewman/static/app/common/md.filter.ts new file mode 100644 index 00000000..63b49906 --- /dev/null +++ b/brewman/static/app/common/md.filter.ts @@ -0,0 +1,8 @@ +import {Showdown} from 'showdown'; + +export function Md() { + var converter = new Showdown.converter(); + return function (input) { + return converter.makeHtml(input || ''); + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/message.service.ts b/brewman/static/app/common/message.service.ts new file mode 100644 index 00000000..dc10a193 --- /dev/null +++ b/brewman/static/app/common/message.service.ts @@ -0,0 +1,3 @@ +export function Messages() { + return []; +} diff --git a/brewman/static/app/common/ng-growl.directive.ts b/brewman/static/app/common/ng-growl.directive.ts new file mode 100644 index 00000000..0545f8c8 --- /dev/null +++ b/brewman/static/app/common/ng-growl.directive.ts @@ -0,0 +1,11 @@ +export function NgGrowl(growl, $parse) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + var options = { + dismissFunction: attrs["toClose"] + }; + growl.show(element, scope, options); + } + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/on-return.directive.ts b/brewman/static/app/common/on-return.directive.ts new file mode 100644 index 00000000..ace30ef1 --- /dev/null +++ b/brewman/static/app/common/on-return.directive.ts @@ -0,0 +1,17 @@ +export function OnReturn($parse) { + return { + compile: function ($element, attr) { + var fn = $parse(attr.onReturn); + return function (scope, element) { + element.on("keypress", function (event) { + if (event.which === 13) { + scope.$apply(function () { + fn(scope, {$event: event}); + }); + event.preventDefault(); + } + }); + }; + } + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/percent.filter.ts b/brewman/static/app/common/percent.filter.ts new file mode 100644 index 00000000..396f77c8 --- /dev/null +++ b/brewman/static/app/common/percent.filter.ts @@ -0,0 +1,10 @@ +import * as angular from 'angular'; + +export function Percent(numberFilter) { + return function (input) { + if (!angular.isNumber(input)) { + return input; + } + return numberFilter(input * 100, 2) + '%'; + }; +} diff --git a/brewman/static/app/common/posted.filter.ts b/brewman/static/app/common/posted.filter.ts new file mode 100644 index 00000000..758bbf4c --- /dev/null +++ b/brewman/static/app/common/posted.filter.ts @@ -0,0 +1,5 @@ +export function Posted () { + return function (input) { + return input === true ? 'Posted' : 'Post'; + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/reader-promise.service.ts b/brewman/static/app/common/reader-promise.service.ts new file mode 100644 index 00000000..b7c91ca5 --- /dev/null +++ b/brewman/static/app/common/reader-promise.service.ts @@ -0,0 +1,46 @@ +import * as angular from 'angular'; + +export function ReaderPromise($q) { + const onLoad = function (reader, deferred) { + return function () { + deferred.resolve(reader.result); + }; + }; + + const onError = function (reader, deferred) { + return function () { + deferred.reject(reader.result); + }; + }; + + const onProgress = function (reader, scope) { + return function (event) { + scope.$emit("fileProgress", + { + total: event.total, + loaded: event.loaded + }); + }; + }; + + const getReader = function (deferred, scope) { + const reader = new FileReader(); + reader.onload = onLoad(reader, deferred); + reader.onerror = onError(reader, deferred); + if (!angular.isUndefined(scope)) { + reader.onprogress = onProgress(reader, scope); + } + return reader; + }; + + const readAsDataURL = function (file, scope) { + const deferred = $q.defer(), + reader = getReader(deferred, scope); + reader.readAsDataURL(file); + return deferred.promise; + }; + + return { + readAsDataURL: readAsDataURL + }; +} diff --git a/brewman/static/app/common/saveButtonText.filter.ts b/brewman/static/app/common/saveButtonText.filter.ts new file mode 100644 index 00000000..d7604188 --- /dev/null +++ b/brewman/static/app/common/saveButtonText.filter.ts @@ -0,0 +1,5 @@ +export function SaveButtonText() { + return function (input) { + return (!input) ? 'Save' : 'Update'; + }; +} diff --git a/brewman/static/app/common/tan-click.directive.ts b/brewman/static/app/common/tan-click.directive.ts new file mode 100644 index 00000000..c458cd94 --- /dev/null +++ b/brewman/static/app/common/tan-click.directive.ts @@ -0,0 +1,27 @@ +import * as angular from 'angular'; + +export function TanClick($parse, $timeout) { + return { + compile: function ($element, attr) { + var fn = $parse(attr.tanClick); + return function (scope, element, attr) { + element.on('click', function (event) { + scope.$apply(function () { + var disabled = attr.ngDisabled ? $parse(attr.ngDisabled) : angular.noop; + attr.$set('disabled', true); + var v = fn(scope, {$event: event}) || angular.noop; + if (v && v.then) { + v.finally(function () { + attr.$set('disabled', !!disabled(scope) || false); + }); + } else { + $timeout(function () { + attr.$set('disabled', !!disabled(scope) || false); + }, 5000); + } + }); + }); + }; + } + }; +} \ No newline at end of file diff --git a/brewman/static/app/common/tokenizer.service.ts b/brewman/static/app/common/tokenizer.service.ts new file mode 100644 index 00000000..75fd8127 --- /dev/null +++ b/brewman/static/app/common/tokenizer.service.ts @@ -0,0 +1,145 @@ +import * as moment from 'moment'; +import * as _ from 'lodash'; + +export function Tokenizer($filter) { + var parseFilterString = function (q, searchInfo) { + // '[^']+'|"[^"]+"|[^ ]+ == Match a space delimited string or quoted string. ms for short + // ((ms\s*:\s*ms)|ms) == Match string : Match string OR Match string + var re = /((('[^']+'|"[^"]+"|[^\s]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))|('[^']+'|"[^"]+"|[^\s]+))/g, + comparator = searchInfo.comparator || {}, + sorter = searchInfo.sorter || {}, + flagger = searchInfo.flags || {}, + defaultKey = searchInfo.def, + matches = [], + sorting = [], + flags = {}, + operators = { + '<': function (a, b) { + return a < b; + }, + '>': function (a, b) { + return a > b; + }, + '<=': function (a, b) { + return a <= b; + }, + '>=': function (a, b) { + return a >= b; + }, + '==': function (a, b) { + return a === b; + }, + '!=': function (a, b) { + return a !== b; + } + }, + comparators = { + 'text': function (obj, text) { + if (text.indexOf('!') === 0) { + return !obj.toLowerCase().includes(text.substr(1).toLowerCase()); + } else { + return obj.toLowerCase().includes(text.toLowerCase()); + } + }, + 'date': function (obj, text) { + var obDate = moment(obj, 'DD-MMM-YYYY'), + op = operatorLength(text), + operator = op ? text.substr(0, op) : '==', + textDate = op ? moment(text.substr(op).trim(), 'DD-MMM-YYYY') : moment(text, 'DD-MMM-YYYY'); + return !obDate.isValid() || !textDate.isValid() || operators[operator](obDate.valueOf(), textDate.valueOf()); + }, + 'boolean': function (obj, text) { + return obj === isTrue(text); + }, + 'numeric': function (obj, text) { + var op = operatorLength(text); + if (op) { + return operators[text.substr(0, op)](obj, Number(text.substr(op).trim())); + } else { + return obj.toString().indexOf(text) > -1; + } + }, + 'true': function () { + return true; + } + }; + + function isTrue(value) { + return !_.any(['f', 'fa', 'fal', 'fals', 'false', 'n', 'no', '0'], function (item) { + return item === value; + }); + } + + function is(ch, chars) { + return chars.indexOf(ch) !== -1; + } + + function pushObject(comparator, value) { + return {'Col': comparator.Col, 'Comparator': comparators[comparator.Comparator], 'Value': value}; + } + + function operatorLength(operator) { + var i, + ops = ['<=', '<', '>=', '>', '==', '!=']; + for (i = 0; i < ops.length; i++) { + if (operator.indexOf(ops[i]) === 0) { + return ops[i].length; + } + } + return 0; + } + + _(q.match(re)) + .reduce(function (accumulator, item) { + var key, + value; + if (item.indexOf(':') === -1) { + key = ''; + value = item; + } else { + key = item.substr(0, item.indexOf(':')).trim(); + value = item.substr(item.indexOf(':') + 1, item.length).trim(); + } + if (key.indexOf("'") !== -1 || key.indexOf('"') !== -1) { + key = key.substring(1, key.length - 1).trim(); + } + if (value.indexOf("'") !== -1 || value.indexOf('"') !== -1) { + value = value.substring(1, value.length - 1).trim(); + } + if (value !== '') { + accumulator.push({Key: key, Value: value}); + } + return accumulator; + }, []) + .forEach(function (item) { + var key = item.Key, + value = item.Value; + + if (key === '' && value.length > 1 && is(value.charAt(0), '+-') && value.substr(1) in sorter) { + sorting.push(value.charAt(0) + sorter[value.substr(1).toLowerCase()]); + } else { + key = key || defaultKey; + if (key in comparator) { + matches.push(pushObject(comparator[key], value)); + } else if (key in flagger) { + flags[key] = value; + } + } + }); + return {'q': matches, 'o': sorting, 'f': flags}; + }; + var doFilter = function (q, array, matches) { + var filterExpressions = matches.q, + sortPredicates = matches.o, + filterCount = filterExpressions.length; + var arrayCopy = filterCount === 0 ? array : _.filter(array, function (item) { + return _.every(filterExpressions, function (expression) { + return expression.Comparator(item[expression.Col], expression.Value); + }); + }); + arrayCopy = $filter('orderBy')(arrayCopy, sortPredicates); + return arrayCopy; + }; + + return {parseFilterString: parseFilterString, doFilter: doFilter}; +} diff --git a/brewman/static/app/common/upload-image-resizer.service.ts b/brewman/static/app/common/upload-image-resizer.service.ts new file mode 100644 index 00000000..a16c752c --- /dev/null +++ b/brewman/static/app/common/upload-image-resizer.service.ts @@ -0,0 +1,52 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; + +export function UploadedImageResizer($q, ReaderPromise) { + function resizeImage(file, MAX_WIDTH, MAX_HEIGHT) { + var image = file, + canvas = document.createElement('canvas'), + ctx = canvas.getContext("2d"), + img = document.createElement("img"), + ratio = 1; + + img.src = image; + var width = img.width, + height = img.height; + + if (width > MAX_WIDTH) { + ratio = MAX_WIDTH / width; + } + if (height > MAX_HEIGHT && MAX_HEIGHT / height < ratio) { + ratio = MAX_HEIGHT / height; + } + if (ratio === 1) { + return file; + } + + width *= ratio; + height *= ratio; + + canvas.width = width; + canvas.height = height; + ctx.drawImage(img, 0, 0, width, height); + return canvas.toDataURL("image/jpeg", 0.95); + } + + var ProcessUpload = function (uploadedFile, oldFiles) { + var file:any = {File: uploadedFile.file}, + exists = _.some(oldFiles, function (value) { + return angular.equals(value.File, file.File); + }); + + if (exists) { + return; + } + ReaderPromise.readAsDataURL(uploadedFile.file).then(function (result) { + file.Original = result; + file.Thumbnail = resizeImage(result, 100, 150); + file.Resized = resizeImage(result, 825, 1170); + }); + oldFiles.push(file); + }; + return ProcessUpload; +} diff --git a/brewman/static/app/common/voucher.service.ts b/brewman/static/app/common/voucher.service.ts new file mode 100644 index 00000000..63bdf65a --- /dev/null +++ b/brewman/static/app/common/voucher.service.ts @@ -0,0 +1,44 @@ +import * as angular from 'angular'; + +export function Voucher($resource) { + return $resource('/api/Voucher/:id', + {id: '@VoucherID'}, { + post: {method: 'POST', params: {post: true}}, + save: { + method: 'POST', + headers: {'Content-Type': undefined}, + transformRequest: function (orgData, headers) { + var data = angular.copy(orgData); + + function dataURLtoBlob(dataURL) { + var re = /^data:([\w/\-\.]+);\w+,(.*)$/, + m = dataURL.match(re), + mimeString = m[1], + byteString = atob(m[2]), + ab = new ArrayBuffer(byteString.length), + dw = new DataView(ab), + i; + + for (i = 0; i < byteString.length; i++) { + dw.setUint8(i, byteString.charCodeAt(i)); + } + return new Blob([ab], {type: mimeString}); + } + + let fd = new FormData(), + files = [], + i; + for (i = data.Files.length - 1; i >= 0; i--) { + let item = data.Files[i]; + if (!item.ID) { + fd.append('f' + i, dataURLtoBlob(item.Resized)); + fd.append('t' + i, dataURLtoBlob(item.Thumbnail)); + data.Files.splice(i, 1); + } + } + fd.append('model', angular.toJson(data)); + return fd; + } + } + }); +} diff --git a/brewman/static/app/cost-centre/cost-centre-detail.html b/brewman/static/app/cost-centre/cost-centre-detail.html index 5748d295..9b5b8e08 100644 --- a/brewman/static/app/cost-centre/cost-centre-detail.html +++ b/brewman/static/app/cost-centre/cost-centre-detail.html @@ -5,12 +5,12 @@
- +
- +
diff --git a/brewman/static/app/cost-centre/cost-centre-list.component.ts b/brewman/static/app/cost-centre/cost-centre-list.component.ts new file mode 100644 index 00000000..8dc04026 --- /dev/null +++ b/brewman/static/app/cost-centre/cost-centre-list.component.ts @@ -0,0 +1,7 @@ +import {CostCentreListController} from './cost-centre-list.controller'; + +export const CostCentreListComponent = { + templateUrl: '/app/cost-centre/cost-centre-list.html', + controller: CostCentreListController, + controllerAs: 'vm' +}; diff --git a/brewman/static/app/cost-centre/cost-centre-list.controller.js b/brewman/static/app/cost-centre/cost-centre-list.controller.js deleted file mode 100644 index 34fd53b9..00000000 --- a/brewman/static/app/cost-centre/cost-centre-list.controller.js +++ /dev/null @@ -1,14 +0,0 @@ -angular - .module('overlord') - .controller('CostCentreListController', CostCentreListController); - -CostCentreListController.$inject = ['$scope', 'costCentres']; -function CostCentreListController($scope, costCentres) { - $scope.info = costCentres; -} - -CostCentreListController.resolve = { - costCentres: ['CostCentre', function (CostCentre) { - return CostCentre.query({}).$promise; - }] -}; diff --git a/brewman/static/app/cost-centre/cost-centre-list.controller.ts b/brewman/static/app/cost-centre/cost-centre-list.controller.ts new file mode 100644 index 00000000..c23afa62 --- /dev/null +++ b/brewman/static/app/cost-centre/cost-centre-list.controller.ts @@ -0,0 +1,10 @@ +export class CostCentreListController { + static $inject = ['$scope']; + info: any; + costCentres: any; + + constructor(public $scope) { + this.costCentres = $scope.$parent.res.costCentres; + this.info = this.costCentres; + } +} diff --git a/brewman/static/app/cost-centre/cost-centre-list.html b/brewman/static/app/cost-centre/cost-centre-list.html index 8e686965..d93dd4ce 100644 --- a/brewman/static/app/cost-centre/cost-centre-list.html +++ b/brewman/static/app/cost-centre/cost-centre-list.html @@ -6,7 +6,7 @@ - + {{item.Name}} diff --git a/brewman/static/app/cost-centre/cost-centre-list.resolver.ts b/brewman/static/app/cost-centre/cost-centre-list.resolver.ts new file mode 100644 index 00000000..341c5fd6 --- /dev/null +++ b/brewman/static/app/cost-centre/cost-centre-list.resolver.ts @@ -0,0 +1,3 @@ +export function CostCentreListResolver(CostCentre) { + return CostCentre.query({}).$promise; +} diff --git a/brewman/static/app/cost-centre/cost-centre.component.ts b/brewman/static/app/cost-centre/cost-centre.component.ts new file mode 100644 index 00000000..ca3440ad --- /dev/null +++ b/brewman/static/app/cost-centre/cost-centre.component.ts @@ -0,0 +1,7 @@ +import {CostCentreController} from './cost-centre.controller'; + +export const CostCentreComponent = { + templateUrl: '/app/cost-centre/cost-centre-detail.html', + controller: CostCentreController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/cost-centre/cost-centre.controller.js b/brewman/static/app/cost-centre/cost-centre.controller.js deleted file mode 100644 index 255e0217..00000000 --- a/brewman/static/app/cost-centre/cost-centre.controller.js +++ /dev/null @@ -1,34 +0,0 @@ -angular - .module('overlord') - .controller('CostCentreController', CostCentreController); - -CostCentreController.$inject = ['$scope', '$routeParams', '$location', 'costCentre']; -function CostCentreController($scope, $routeParams, $location, costCentre) { - $scope.costCentre = costCentre; - - $scope.save = function () { - $scope.costCentre.$save(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/CostCentres') - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.costCentre.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/CostCentres') - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.foName = true; -} - -CostCentreController.resolve = { - costCentre: ['$route', 'CostCentre', function ($route, CostCentre) { - var id = $route.current.params.id; - return CostCentre.get({id: id}).$promise; - }] -}; diff --git a/brewman/static/app/cost-centre/cost-centre.controller.ts b/brewman/static/app/cost-centre/cost-centre.controller.ts new file mode 100644 index 00000000..62d5477b --- /dev/null +++ b/brewman/static/app/cost-centre/cost-centre.controller.ts @@ -0,0 +1,28 @@ +export class CostCentreController { + static $inject = ['$scope', '$routeParams', '$location', 'Messages']; + foName: any; + costCentre: any; + + constructor(public $scope, public $routeParams, public $location, public Messages) { + this.costCentre = $scope.$parent.res.costCentre; + this.foName = true; + } + + save() { + this.costCentre.$save((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/CostCentres') + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.costCentre.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/CostCentres') + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } +} diff --git a/brewman/static/app/cost-centre/cost-centre.resolver.ts b/brewman/static/app/cost-centre/cost-centre.resolver.ts new file mode 100644 index 00000000..01804f2b --- /dev/null +++ b/brewman/static/app/cost-centre/cost-centre.resolver.ts @@ -0,0 +1,4 @@ +export function CostCentreResolver($route, CostCentre) { + const id = $route.current.params.id; + return CostCentre.get({id: id}).$promise; +} diff --git a/brewman/static/app/cost-centre/cost-centre.service.ts b/brewman/static/app/cost-centre/cost-centre.service.ts new file mode 100644 index 00000000..707f91f6 --- /dev/null +++ b/brewman/static/app/cost-centre/cost-centre.service.ts @@ -0,0 +1,6 @@ +export function CostCentre($resource) { + return $resource('/api/CostCentre/:id', + {id: '@CostCentreID'}, { + query: {method: 'GET', params: {list: true}, isArray: true} + }); +} diff --git a/brewman/static/app/daybook/daybook.component.ts b/brewman/static/app/daybook/daybook.component.ts new file mode 100644 index 00000000..48ddcb57 --- /dev/null +++ b/brewman/static/app/daybook/daybook.component.ts @@ -0,0 +1,7 @@ +import {DaybookController} from './daybook.controller'; + +export const DaybookComponent = { + templateUrl: '/app/daybook/daybook.html', + controller: DaybookController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/daybook/daybook.controller.js b/brewman/static/app/daybook/daybook.controller.js deleted file mode 100644 index 0973ba05..00000000 --- a/brewman/static/app/daybook/daybook.controller.js +++ /dev/null @@ -1,40 +0,0 @@ -angular - .module('overlord') - .controller('DaybookController', DaybookController); - -DaybookController.$inject = ['$scope', '$location', 'asDateFilter', 'info', 'uibDateParser']; -function DaybookController($scope, $location, asDate, info, dateParser) { - var _info_StartDate = dateParser.parse(info.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(info.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = info; - $scope.show = function () { - $location.path('/Daybook').search({StartDate: $scope.info.StartDate, FinishDate: $scope.info.FinishDate}); - }; - $scope.foDate = true; -} -DaybookController.resolve = { - info: ['$route', 'Daybook', function ($route, Daybook) { - var startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return Daybook.get({}).$promise; - } else { - return Daybook.get({StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; \ No newline at end of file diff --git a/brewman/static/app/daybook/daybook.controller.ts b/brewman/static/app/daybook/daybook.controller.ts new file mode 100644 index 00000000..9d3d75fc --- /dev/null +++ b/brewman/static/app/daybook/daybook.controller.ts @@ -0,0 +1,36 @@ +import * as angular from 'angular'; + +export class DaybookController { + static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + _info_StartDate:any; + _info_FinishDate:any; + foDate:boolean; + info:any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.info = $scope.$parent.res.info; + this._info_StartDate = dateParser.parse(this.info.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.info.FinishDate, "dd-MMM-yyyy"); + this.foDate = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this. _info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/Daybook').search({StartDate: this.info.StartDate, FinishDate: this.info.FinishDate}); + } +} diff --git a/brewman/static/app/daybook/daybook.html b/brewman/static/app/daybook/daybook.html index f715ec03..8db1728b 100644 --- a/brewman/static/app/daybook/daybook.html +++ b/brewman/static/app/daybook/daybook.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
@@ -41,7 +41,7 @@ - + diff --git a/brewman/static/app/daybook/daybook.resolver.ts b/brewman/static/app/daybook/daybook.resolver.ts new file mode 100644 index 00000000..dd7a5055 --- /dev/null +++ b/brewman/static/app/daybook/daybook.resolver.ts @@ -0,0 +1,12 @@ +import * as angular from 'angular'; + +export function DaybookResolver($route, Daybook) { + const startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return Daybook.get({}).$promise; + } else { + return Daybook.get({StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/daybook/daybook.service.ts b/brewman/static/app/daybook/daybook.service.ts new file mode 100644 index 00000000..67637ee2 --- /dev/null +++ b/brewman/static/app/daybook/daybook.service.ts @@ -0,0 +1,3 @@ +export function Daybook($resource) { + return $resource('/api/Daybook'); +} diff --git a/brewman/static/app/employee/employee-attendance-info.resolver.ts b/brewman/static/app/employee/employee-attendance-info.resolver.ts new file mode 100644 index 00000000..24327b5c --- /dev/null +++ b/brewman/static/app/employee/employee-attendance-info.resolver.ts @@ -0,0 +1,13 @@ +import * as angular from 'angular'; + +export function EmployeeAttendanceInfoResolver($route, EmployeeAttendance) { + const id = $route.current.params.id, + startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(id)) { + return EmployeeAttendance.get({}).$promise; + } else { + return EmployeeAttendance.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/employee/employee-attendance-sub.directive.ts b/brewman/static/app/employee/employee-attendance-sub.directive.ts new file mode 100644 index 00000000..010aa7d5 --- /dev/null +++ b/brewman/static/app/employee/employee-attendance-sub.directive.ts @@ -0,0 +1,14 @@ +import {AttendanceSubController} from "../attendance/attendance-sub.controller"; + +export function EmployeeAttendanceSubDirective() { + return { + scope: { + item: '=employeeAttendanceSub', + attendanceTypes: '=attendanceTypes' + }, + restrict: 'A', + templateUrl: '/app/employee/employee-attendance-sub.html', + controller: AttendanceSubController, + controllerAs: 'vmSub', + }; +} diff --git a/brewman/static/app/employee/employee-attendance-sub.html b/brewman/static/app/employee/employee-attendance-sub.html new file mode 100644 index 00000000..6df01970 --- /dev/null +++ b/brewman/static/app/employee/employee-attendance-sub.html @@ -0,0 +1,12 @@ + + + + diff --git a/brewman/static/app/employee/employee-attendance.component.ts b/brewman/static/app/employee/employee-attendance.component.ts new file mode 100644 index 00000000..a0120d77 --- /dev/null +++ b/brewman/static/app/employee/employee-attendance.component.ts @@ -0,0 +1,7 @@ +import {EmployeeAttendanceController} from './employee-attendance.controller'; + +export const EmployeeAttendanceComponent = { + templateUrl: '/app/employee/employee-attendance.html', + controller: EmployeeAttendanceController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/employee/employee-attendance.controller.js b/brewman/static/app/employee/employee-attendance.controller.js deleted file mode 100644 index 95688e3e..00000000 --- a/brewman/static/app/employee/employee-attendance.controller.js +++ /dev/null @@ -1,100 +0,0 @@ -angular - .module('overlord') - .controller('EmployeeAttendanceController', EmployeeAttendanceController); -EmployeeAttendanceController.$inject = ['$scope', '$location', '$routeParams', 'asDateFilter', 'EmployeeAttendance', 'attendanceTypes', 'info', 'Employee', 'uibDateParser']; -function EmployeeAttendanceController($scope, $location, $routeParams, asDate, EmployeeAttendance, attendanceTypes, info, Employee, dateParser) { - var _info_StartDate = dateParser.parse(info.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(info.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.attendanceTypes = attendanceTypes; - $scope.info = info; - $scope.show = function () { - var id = $scope.info.Employee.LedgerID; - if (id === $routeParams.id && $scope.info.StartDate === $routeParams.StartDate && $scope.info.FinishDate === $routeParams.FinishDate) { - EmployeeAttendance.get({ - id: id, - StartDate: $scope.info.StartDate, - FinishDate: $scope.info.FinishDate - }, function (data) { - $scope.info = data; - }); - } - else { - $location.path('/EmployeeAttendance/' + id).search({ - StartDate: $scope.info.StartDate, - FinishDate: $scope.info.FinishDate - }); - } - }; - - $scope.employees = function ($viewValue) { - return Employee.autocomplete({term: $viewValue, count: 20}).$promise; - }; - - $scope.save = function () { - return $scope.info.$save(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: 'Saved!'}); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.foEmployee = true; -} - -angular - .module('overlord') - .controller('EmployeeAttendanceSubController', EmployeeAttendanceSubController); -EmployeeAttendanceSubController.$inject = ['$scope']; -function EmployeeAttendanceSubController($scope) { - $scope.original = {}; - angular.copy($scope.item, $scope.original); - - $scope.isLabel = function () { - return true; - }; - - $scope.isError = function () { - return $scope.item.Worked === 'Error'; - }; - - $scope.isGood = function () { - return $scope.item.Worked === true; - }; - - $scope.isBad = function () { - return $scope.item.Worked === false; - }; - - $scope.isDirty = function () { - return !angular.equals($scope.original, $scope.item); - }; -} -EmployeeAttendanceController.resolve = { - info: ['$route', 'EmployeeAttendance', function ($route, EmployeeAttendance) { - var id = $route.current.params.id, - startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(id)) { - return EmployeeAttendance.get({}).$promise; - } else { - return EmployeeAttendance.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; - } - }], - attendanceTypes: ['AttendanceTypes', function (AttendanceTypes) { - return AttendanceTypes.query({}).$promise; - }] -}; \ No newline at end of file diff --git a/brewman/static/app/employee/employee-attendance.controller.ts b/brewman/static/app/employee/employee-attendance.controller.ts new file mode 100644 index 00000000..0d200ff6 --- /dev/null +++ b/brewman/static/app/employee/employee-attendance.controller.ts @@ -0,0 +1,64 @@ +export class EmployeeAttendanceController { + static $inject = ['$scope', '$location', '$routeParams', 'asDateFilter', 'EmployeeAttendance', 'Employee', 'uibDateParser', 'Messages']; + _info_StartDate: any; + _info_FinishDate: any; + foEmployee: boolean; + item: any; + attendanceTypes: any; + info: any; + + constructor(public $scope, public $location, public $routeParams, public asDate, public EmployeeAttendance, public Employee, public dateParser, public Messages) { + this.attendanceTypes = $scope.$parent.res.attendanceTypes; + this.info = $scope.$parent.res.info; + this._info_StartDate = dateParser.parse(this.info.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.info.FinishDate, "dd-MMM-yyyy"); + this.foEmployee = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + const id = this.info.Employee.LedgerID; + if (id === this.$routeParams.id && this.info.StartDate === this.$routeParams.StartDate && this.info.FinishDate === this.$routeParams.FinishDate) { + this.EmployeeAttendance.get({ + id: id, + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }, (data) => { + this.info = data; + }); + } + else { + this.$location.path('/EmployeeAttendance/' + id).search({ + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }); + } + } + + employees($viewValue) { + return this.Employee.autocomplete({term: $viewValue, count: 20}).$promise; + } + + save() { + return this.info.$save((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: 'Saved!'}); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } +} diff --git a/brewman/static/app/employee/employee-attendance.html b/brewman/static/app/employee/employee-attendance.html index abd45571..2c2fadf6 100644 --- a/brewman/static/app/employee/employee-attendance.html +++ b/brewman/static/app/employee/employee-attendance.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -30,11 +30,12 @@
- - -
@@ -50,27 +51,14 @@
- - - - - +
{{item.Date}} {{item.Type}} {{item.Narration}}{{item.Date}} + + +{{item.Prints}} {{item.Hours}} + + +
{{item.Date}} - - - {{item.Prints}} {{item.Hours}} - - -
- +
diff --git a/brewman/static/app/employee/employee-attendance.service.ts b/brewman/static/app/employee/employee-attendance.service.ts new file mode 100644 index 00000000..a864c7e0 --- /dev/null +++ b/brewman/static/app/employee/employee-attendance.service.ts @@ -0,0 +1,3 @@ +export function EmployeeAttendance($resource) { + return $resource('/api/EmployeeAttendance/:id', {id: '@Employee.LedgerID'}); +} diff --git a/brewman/static/app/employee/employee-detail.html b/brewman/static/app/employee/employee-detail.html index e19dec79..c3a6b8b6 100644 --- a/brewman/static/app/employee/employee-detail.html +++ b/brewman/static/app/employee/employee-detail.html @@ -5,42 +5,42 @@
- +
- +
- +
- +
- +
@@ -49,8 +49,8 @@
- +
@@ -60,7 +60,7 @@
@@ -68,13 +68,13 @@
-
+
@@ -84,8 +84,8 @@
- - + +
diff --git a/brewman/static/app/employee/employee-functions.component.ts b/brewman/static/app/employee/employee-functions.component.ts new file mode 100644 index 00000000..7f1b5a8a --- /dev/null +++ b/brewman/static/app/employee/employee-functions.component.ts @@ -0,0 +1,7 @@ +import {EmployeeFunctionsController} from './employee-functions.controller'; + +export const EmployeeFunctionsComponent = { + templateUrl: '/app/employee/employee-functions.html', + controller: EmployeeFunctionsController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/employee/employee-functions.controller.js b/brewman/static/app/employee/employee-functions.controller.js deleted file mode 100644 index 51c2feb4..00000000 --- a/brewman/static/app/employee/employee-functions.controller.js +++ /dev/null @@ -1,68 +0,0 @@ -angular - .module('overlord') - .controller('EmployeeFunctionsController', EmployeeFunctionsController); -EmployeeFunctionsController.$inject = ['$scope', '$http', 'asDateFilter']; -function EmployeeFunctionsController($scope, $http, asDate) { - var _record_StartDate, - _record_FinishDate; - $scope.record_StartDate = function (value) { - if (arguments.length) { - $scope.record.StartDate = asDate(value); - _record_StartDate = value; - } - return _record_StartDate; - }; - $scope.record_FinishDate = function (value) { - if (arguments.length) { - $scope.record.FinishDate = asDate(value); - _record_FinishDate = value; - } - return _record_FinishDate; - }; - $scope.record = {}; - $scope.creditSalary = function () { - if (!angular.isDate($scope.salaryMonth)) { - return; - } - return $http. - post('/api/CreditSalary', {Month: asDate($scope.salaryMonth)}). - success(function (data) { - $scope.toasts.push({Type: 'Success', Message: data.message}); - }). - error(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage}); - }); - }; - - $scope.attendanceRecordUrl = function () { - if (!$scope.record.StartDate || !$scope.record.FinishDate) { - return; - } - - var url = '/AttendanceReport?StartDate=' + $scope.record.StartDate + "&FinishDate=" + $scope.record.FinishDate; - return url; - }; - $scope.setFile = function (element) { - $scope.uploadedFile = element.files[0]; - }; - $scope.uploadFingerprints = function () { - if (!$scope.uploadedFile) { - $scope.toasts.push({Type: 'Danger', Message: 'Please choose a file first!'}); - return; - } - var fd = new FormData(); - fd.append("uploadedFile", $scope.uploadedFile); - return $http - .post('/api/Fingerprint', fd, { - headers: { - 'Content-Type': undefined - }, - transformRequest: angular.identity - }).success(function () { - $scope.toasts.push({Type: 'Success', Message: 'Data uploaded'}); - }).error(function (data) { - $scope.toasts.push({Type: 'Danger', Message: data}); - }); - }; -} - diff --git a/brewman/static/app/employee/employee-functions.controller.ts b/brewman/static/app/employee/employee-functions.controller.ts new file mode 100644 index 00000000..bf47ce9c --- /dev/null +++ b/brewman/static/app/employee/employee-functions.controller.ts @@ -0,0 +1,74 @@ +import * as angular from 'angular'; + +export class EmployeeFunctionsController { + static $inject = ['$scope', '$http', 'asDateFilter', 'Messages']; + _record_StartDate: any; + _record_FinishDate: any; + record: any; + uploadedFile: any; + salaryMonth: any; + + constructor(public $scope, public $http, public asDate, public Messages) { + this._record_StartDate = undefined; + this._record_FinishDate = undefined; + this.record = {}; + } + + record_StartDate(value) { + if (arguments.length) { + this.record.StartDate = this.asDate(value); + this._record_StartDate = value; + } + return this._record_StartDate; + } + + record_FinishDate(value) { + if (arguments.length) { + this.record.FinishDate = this.asDate(value); + this._record_FinishDate = value; + } + return this._record_FinishDate; + } + + creditSalary() { + if (!angular.isDate(this.salaryMonth)) { + return; + } + return this.$http.post('/api/CreditSalary', {Month: this.asDate(this.salaryMonth)}).success((data) => { + this.Messages.push({Type: 'Success', Message: data.message}); + }).error((errorMessage) => { + this.Messages.push({Type: 'Danger', Message: errorMessage}); + }); + } + + attendanceRecordUrl() { + if (!this.record.StartDate || !this.record.FinishDate) { + return; + } + return '/AttendanceReport?StartDate=' + this.record.StartDate + "&FinishDate=" + this.record.FinishDate; + } + + setFile(element) { + this.uploadedFile = element.files[0]; + } + + uploadFingerprints() { + if (!this.uploadedFile) { + this.Messages.push({Type: 'Danger', Message: 'Please choose a file first!'}); + return; + } + let fd = new FormData(); + fd.append("uploadedFile", this.uploadedFile); + return this.$http + .post('/api/Fingerprint', fd, { + headers: { + 'Content-Type': undefined + }, + transformRequest: angular.identity + }).success(() => { + this.Messages.push({Type: 'Success', Message: 'Data uploaded'}); + }).error((data) => { + this.Messages.push({Type: 'Danger', Message: data}); + }); + } +} diff --git a/brewman/static/app/employee/employee-functions.html b/brewman/static/app/employee/employee-functions.html index 3f9434ab..775bd30e 100644 --- a/brewman/static/app/employee/employee-functions.html +++ b/brewman/static/app/employee/employee-functions.html @@ -7,14 +7,14 @@
+ datepicker-mode="month" is-open="vm.smdOpen" ng-focus="vm.smdOpen = true" ng-model="vm.salaryMonth"/>
-
@@ -27,7 +27,7 @@
@@ -37,7 +37,7 @@
@@ -45,7 +45,7 @@
@@ -61,7 +61,7 @@ onchange="angular.element(this).scope().setFile(this)"/>
-
diff --git a/brewman/static/app/employee/employee-list.component.ts b/brewman/static/app/employee/employee-list.component.ts new file mode 100644 index 00000000..7734097e --- /dev/null +++ b/brewman/static/app/employee/employee-list.component.ts @@ -0,0 +1,7 @@ +import {EmployeeListController} from './employee-list.controller'; + +export const EmployeeListComponent = { + templateUrl: '/app/employee/employee-list.html', + controller: EmployeeListController, + controllerAs: 'vm' +}; diff --git a/brewman/static/app/employee/employee-list.controller.js b/brewman/static/app/employee/employee-list.controller.js deleted file mode 100644 index 5434ed15..00000000 --- a/brewman/static/app/employee/employee-list.controller.js +++ /dev/null @@ -1,83 +0,0 @@ -angular - .module('overlord') - .controller('EmployeeListController', EmployeeListController); - -EmployeeListController.$inject = ['$scope', '$location', '$routeParams', 'Tokenizer', 'employees']; -function EmployeeListController($scope, $location, $routeParams, Tokenizer, employees) { - $scope.search = $routeParams.q || ''; - $scope.info = employees; - - $scope.$watch('search', function (newValue, oldValue) { - $scope.filterEmployees(newValue); - }, true); - - $scope.$on('$destroy', function () { - Tokenizer.doFilter.cache = {}; - }); - - $scope.searchInfo = { - comparator: { - 'n': {'Col': 'Name', 'Comparator': 'text'}, - 'c': {'Col': 'Code', 'Comparator': 'numeric'}, - 's': {'Col': 'Salary', 'Comparator': 'numeric'}, - 'a': {'Col': 'IsActive', 'Comparator': 'boolean'}, - 'des': {'Col': 'Designation', 'Comparator': 'text'}, - 'dep': {'Col': 'CostCentre', 'Comparator': 'text'} - }, - def: 'n', - sorter: { - 'n': 'Name', - 'c': 'Code', - 's': 'Salary', - 'a': 'IsActive', - 'des': 'Designation', - 'dep': 'CostCentre' - } - }; - $scope.filterEmployees = _.debounce(function (q) { - if (q !== $scope._search) { - $scope._search = q; - if (angular.isUndefined(q) || q === '') { - $location.path('/Employees').search('q', null).replace(); - } else { - $location.path('/Employees').search({'q': q}).replace(); - } - $scope.$apply(function () { - var matches = Tokenizer.parseFilterString(q, $scope.searchInfo); - $scope.employees = Tokenizer.doFilter(q, $scope.info, matches); - - }); - } - }, 350); - - $scope.selected = -1; - $scope.setSelected = function (index) { - $scope.selected = Math.min(Math.max(0, index), $scope.employees.length - 1); - }; - $scope.shortcuts = { - 'up': function (e) { - if ($scope.selected > 0) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected - 1), $scope.employees.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - }, - 'down': function (e) { - if ($scope.selected < $scope.employees.length - 1) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected + 1), $scope.employees.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - } - }; -} - -EmployeeListController.resolve = { - employees: ['Employee', function (Employee) { - return Employee.query({}).$promise; - }] -}; diff --git a/brewman/static/app/employee/employee-list.controller.ts b/brewman/static/app/employee/employee-list.controller.ts new file mode 100644 index 00000000..ca3e8adb --- /dev/null +++ b/brewman/static/app/employee/employee-list.controller.ts @@ -0,0 +1,88 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import * as $ from 'jquery'; + +export class EmployeeListController { + static $inject = ['$scope', '$location', '$routeParams', 'Tokenizer']; + search: any; + info: any; + searchInfo: any; + filterEmployees: any; + selected: any; + shortcuts: any; + employees: any; + + constructor(public $scope, public $location, public $routeParams, public Tokenizer) { + this.employees = $scope.$parent.res.employees; + this.search = $routeParams.q || ''; + this.info = this.employees; + $scope.$watch('vm.search', (newValue, oldValue) => { + this.filterEmployees(newValue); + }, true); + + $scope.$on('$destroy', () => { + Tokenizer.doFilter.cache = {}; + }); + + this.searchInfo = { + comparator: { + 'n': {'Col': 'Name', 'Comparator': 'text'}, + 'c': {'Col': 'Code', 'Comparator': 'numeric'}, + 's': {'Col': 'Salary', 'Comparator': 'numeric'}, + 'a': {'Col': 'IsActive', 'Comparator': 'boolean'}, + 'des': {'Col': 'Designation', 'Comparator': 'text'}, + 'dep': {'Col': 'CostCentre', 'Comparator': 'text'} + }, + def: 'n', + sorter: { + 'n': 'Name', + 'c': 'Code', + 's': 'Salary', + 'a': 'IsActive', + 'des': 'Designation', + 'dep': 'CostCentre' + } + }; + this.filterEmployees = _.debounce((q) => { + if (q !== $scope._search) { + $scope._search = q; + if (angular.isUndefined(q) || q === '') { + this.$location.path('/Employees').search('q', null).replace(); + } else { + this.$location.path('/Employees').search({'q': q}).replace(); + } + $scope.$apply(() => { + const matches = Tokenizer.parseFilterString(q, this.searchInfo); + this.employees = Tokenizer.doFilter(q, this.info, matches); + + }); + } + }, 350); + + this.selected = -1; + this.shortcuts = { + 'up': (e) => { + if (this.selected > 0) { + $scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected - 1), this.employees.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + }, + 'down': (e) => { + if (this.selected < this.employees.length - 1) { + $scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected + 1), this.employees.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + } + }; + } + + setSelected(index) { + this.selected = Math.min(Math.max(0, index), this.employees.length - 1); + } +} diff --git a/brewman/static/app/employee/employee-list.html b/brewman/static/app/employee/employee-list.html index 69b01dcb..356f574b 100644 --- a/brewman/static/app/employee/employee-list.html +++ b/brewman/static/app/employee/employee-list.html @@ -1,7 +1,7 @@

Employees
- +

- +
@@ -23,8 +23,8 @@ - + diff --git a/brewman/static/app/employee/employee-list.resolver.ts b/brewman/static/app/employee/employee-list.resolver.ts new file mode 100644 index 00000000..634a621e --- /dev/null +++ b/brewman/static/app/employee/employee-list.resolver.ts @@ -0,0 +1,3 @@ +export function EmployeeListResolver(Employee) { + return Employee.query({}).$promise; +} diff --git a/brewman/static/app/employee/employee.component.ts b/brewman/static/app/employee/employee.component.ts new file mode 100644 index 00000000..d5c3fbdf --- /dev/null +++ b/brewman/static/app/employee/employee.component.ts @@ -0,0 +1,7 @@ +import {EmployeeController} from './employee.controller'; + +export const EmployeeComponent = { + templateUrl: '/app/employee/employee-detail.html', + controller: EmployeeController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/employee/employee.controller.js b/brewman/static/app/employee/employee.controller.js deleted file mode 100644 index f8388be1..00000000 --- a/brewman/static/app/employee/employee.controller.js +++ /dev/null @@ -1,75 +0,0 @@ -angular - .module('overlord') - .controller('EmployeeController', EmployeeController); -EmployeeController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', '$uibModal', 'employee', 'costCentres', 'uibDateParser']; -function EmployeeController($scope, $routeParams, $location, asDate, $modal, employee, costCentres, dateParser) { - var _employee_JoiningDate = dateParser.parse(employee.JoiningDate, "dd-MMM-yyyy"), - _employee_LeavingDate = dateParser.parse(employee.LeavingDate, "dd-MMM-yyyy"); - $scope.employee_JoiningDate = function (value) { - if (arguments.length) { - $scope.employee.JoiningDate = asDate(value); - _employee_JoiningDate = value; - } - return _employee_JoiningDate; - }; - $scope.employee_LeavingDate = function (value) { - if (arguments.length) { - $scope.employee.LeavingDate = asDate(value); - _employee_LeavingDate = value; - } - return _employee_LeavingDate; - }; - $scope.employee = employee; - - $scope.costCentres = costCentres; - - $scope.save = function () { - $scope.employee.$save(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: u.Code}); - $location.path('/Employees'); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.employee.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Employees'); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Employee"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - $scope.foName = true; -} - -EmployeeController.resolve = { - employee: ['$route', 'Employee', function ($route, Employee) { - var id = $route.current.params.id; - return Employee.get({id: id}).$promise; - }], - costCentres: ['CostCentre', function (CostCentre) { - return CostCentre.query({}).$promise; - }] -}; diff --git a/brewman/static/app/employee/employee.controller.ts b/brewman/static/app/employee/employee.controller.ts new file mode 100644 index 00000000..19d53545 --- /dev/null +++ b/brewman/static/app/employee/employee.controller.ts @@ -0,0 +1,79 @@ +export class EmployeeController { + static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', '$uibModal', 'uibDateParser', 'Messages']; + _employee_JoiningDate: any; + _employee_LeavingDate: any; + foName: boolean; + employee: any; + costCentres: any; + + constructor(public $scope, public $routeParams, public $location, public asDate, public $modal, public dateParser, public Messages) { + this.employee = $scope.$parent.res.employee; + this.costCentres = $scope.$parent.res.costCentres; + this._employee_JoiningDate = dateParser.parse(this.employee.JoiningDate, "dd-MMM-yyyy"); + this._employee_LeavingDate = dateParser.parse(this.employee.LeavingDate, "dd-MMM-yyyy"); + this.foName = true; + } + + employee_JoiningDate(value) { + if (arguments.length) { + this.employee.JoiningDate = this.asDate(value); + this._employee_JoiningDate = value; + } + return this._employee_JoiningDate; + } + + employee_LeavingDate(value) { + if (arguments.length) { + this.employee.LeavingDate = this.asDate(value); + this._employee_LeavingDate = value; + } + return this._employee_LeavingDate; + } + + save() { + this.employee.$save((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: u.Code}); + this.$location.path('/Employees'); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.employee.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Employees'); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Employee"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } +} diff --git a/brewman/static/app/employee/employee.resolver.ts b/brewman/static/app/employee/employee.resolver.ts new file mode 100644 index 00000000..f4c03377 --- /dev/null +++ b/brewman/static/app/employee/employee.resolver.ts @@ -0,0 +1,4 @@ +export function EmployeeResolver($route, Employee) { + const id = $route.current.params.id; + return Employee.get({id: id}).$promise; +} diff --git a/brewman/static/app/employee/employee.service.ts b/brewman/static/app/employee/employee.service.ts new file mode 100644 index 00000000..f52a9045 --- /dev/null +++ b/brewman/static/app/employee/employee.service.ts @@ -0,0 +1,7 @@ +export function Employee($resource) { + return $resource('/api/Employee/:id', + {id: '@LedgerID'}, { + query: {method: 'GET', params: {list: true}, isArray: true}, + autocomplete: {method: 'GET', params: {term: ''}, isArray: true} + }); +} diff --git a/brewman/static/app/group/group-detail.html b/brewman/static/app/group/group-detail.html index 52029164..e0480d4b 100644 --- a/brewman/static/app/group/group-detail.html +++ b/brewman/static/app/group/group-detail.html @@ -5,24 +5,24 @@
- +
-
+
- +
- +
diff --git a/brewman/static/app/group/group-list.component.ts b/brewman/static/app/group/group-list.component.ts new file mode 100644 index 00000000..4f490b0b --- /dev/null +++ b/brewman/static/app/group/group-list.component.ts @@ -0,0 +1,7 @@ +import {GroupListController} from './group-list.controller'; + +export const GroupListComponent = { + templateUrl: '/app/group/group-list.html', + controller: GroupListController, + controllerAs: 'vm' +}; diff --git a/brewman/static/app/group/group-list.controller.js b/brewman/static/app/group/group-list.controller.js deleted file mode 100644 index c1683616..00000000 --- a/brewman/static/app/group/group-list.controller.js +++ /dev/null @@ -1,13 +0,0 @@ -angular - .module('overlord') - .controller('GroupListController', GroupListController); -GroupListController.$inject = ['$scope', 'groups']; -function GroupListController($scope, groups) { - $scope.info = groups; -} - -GroupListController.resolve = { - groups: ['Group', function (Group) { - return Group.query({}).$promise; - }] -}; diff --git a/brewman/static/app/group/group-list.controller.ts b/brewman/static/app/group/group-list.controller.ts new file mode 100644 index 00000000..5802364b --- /dev/null +++ b/brewman/static/app/group/group-list.controller.ts @@ -0,0 +1,12 @@ +import * as angular from 'angular'; + +export class GroupListController { + static $inject = ['$scope']; + info:any; + groups: any; + + constructor(public $scope) { + this.groups = $scope.$parent.res.groups; + this.info = this.groups; + } +} diff --git a/brewman/static/app/group/group-list.html b/brewman/static/app/group/group-list.html index 3bfb045a..183311fb 100644 --- a/brewman/static/app/group/group-list.html +++ b/brewman/static/app/group/group-list.html @@ -7,7 +7,7 @@
- + - + - + @@ -81,12 +81,12 @@ @@ -99,25 +99,25 @@
- +
- - -
- Created on {{voucher.CreationDate | localTime}} and Last Edited on {{voucher.LastEditDate | localTime}} - by {{voucher.User.Name}}. + Created on {{vm.voucher.CreationDate | localTime}} and Last Edited on {{vm.voucher.LastEditDate | localTime}} + by {{vm.voucher.User.Name}}.
\ No newline at end of file diff --git a/brewman/static/app/journal/journal-modal.controller.js b/brewman/static/app/journal/journal-modal.controller.js deleted file mode 100644 index aa65b317..00000000 --- a/brewman/static/app/journal/journal-modal.controller.js +++ /dev/null @@ -1,28 +0,0 @@ -angular - .module('overlord') - .controller('JournalModalController', JournalModalController); -JournalModalController.$inject = ['$scope', '$uibModalInstance', 'mathSolver', 'edit', 'Account']; -function JournalModalController($scope, $modalInstance, mathSolver, edit, Account) { - $scope.toggleDebit = function () { - $scope.edit.Debit = ($scope.edit.Debit === 1) ? -1 : 1; - }; - - $scope.edit = edit; - $scope.ok = function () { - $scope.edit.Amount = mathSolver($scope.edit.Amount); - if ($scope.edit.Amount < 0) { - $scope.edit.Debit *= -1; - $scope.edit.Amount *= -1; - } - else if (Number.isNaN($scope.edit.Amount)) { - $scope.edit.Amount = 0; - } - $modalInstance.close($scope.edit); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} diff --git a/brewman/static/app/journal/journal-modal.controller.ts b/brewman/static/app/journal/journal-modal.controller.ts new file mode 100644 index 00000000..4470edf6 --- /dev/null +++ b/brewman/static/app/journal/journal-modal.controller.ts @@ -0,0 +1,32 @@ +export class JournalModalController { + static $inject = ['$scope', '$uibModalInstance', 'MathSolver', 'Account']; + edit:any; + + constructor(public $scope, public $modalInstance, public MathSolver, public Account) { + this.edit = $scope.$resolve.edit; + } + + toggleDebit() { + this.edit.Debit = (this.edit.Debit === 1) ? -1 : 1; + } + + ok() { + this.edit.Amount = this.MathSolver(this.edit.Amount); + if (this.edit.Amount < 0) { + this.edit.Debit *= -1; + this.edit.Amount *= -1; + } + else if (Number.isNaN(this.edit.Amount)) { + this.edit.Amount = 0; + } + this.$modalInstance.close(this.edit); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/journal/journal-modal.html b/brewman/static/app/journal/journal-modal.html index 605ebc62..baf4b4bb 100644 --- a/brewman/static/app/journal/journal-modal.html +++ b/brewman/static/app/journal/journal-modal.html @@ -10,24 +10,24 @@
-
-
+ ng-model="vmModal.edit.Amount"/>
\ No newline at end of file diff --git a/brewman/static/app/journal/journal-voucher.resolver.ts b/brewman/static/app/journal/journal-voucher.resolver.ts new file mode 100644 index 00000000..010e23ce --- /dev/null +++ b/brewman/static/app/journal/journal-voucher.resolver.ts @@ -0,0 +1,10 @@ +import * as angular from 'angular'; + +export function JournalVoucherResolver($route, Voucher) { + const id = $route.current.params.id; + if (angular.isUndefined(id)) { + return Voucher.get({type: 'Journal'}).$promise; + } else { + return Voucher.get({id: id}).$promise; + } +} diff --git a/brewman/static/app/journal/journal.component.ts b/brewman/static/app/journal/journal.component.ts new file mode 100644 index 00000000..0be8bcfa --- /dev/null +++ b/brewman/static/app/journal/journal.component.ts @@ -0,0 +1,7 @@ +import {JournalController} from "./journal.controller"; + +export const JournalComponent = { + templateUrl: '/app/journal/journal.html', + controller: JournalController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/journal/journal.controller.js b/brewman/static/app/journal/journal.controller.js deleted file mode 100644 index 53f240c9..00000000 --- a/brewman/static/app/journal/journal.controller.js +++ /dev/null @@ -1,215 +0,0 @@ -angular - .module('overlord') - .controller('JournalController', JournalController); - -JournalController.$inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'uploadedImageResizer', 'mathSolver', 'voucher', 'Account', 'uibDateParser']; - -function JournalController($scope, $location, asDate, $modal, uploadedImageResizer, mathSolver, voucher, Account, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.foAccount = true; - - $scope.voucher = voucher; - $scope.debit = "1"; - function getOld(ledgerID, journals) { - return _.find(journals, function (journal) { - return journal.Ledger.LedgerID === ledgerID; - }); - } - - $scope.$on("fileSelected", function (event, args) { - uploadedImageResizer(args, $scope.voucher.Files); - }); - - - $scope.deleteFile = function (item) { - var index = $scope.voucher.Files.indexOf(item); - $scope.voucher.Files.splice(index, 1); - }; - - $scope.zoomImage = function (item) { - $modal.open({ - templateUrl: '/template/modal/image.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.imageUrl = item.Resized; - $scope.size = null; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - }; - - $scope.add = function () { - var amount, - oldJournal, - debit = parseInt($scope.debit); - - if (!$scope.account || !$scope.account.LedgerID) { - return; - } - amount = mathSolver($scope.amount); - if (Number.isNaN(amount) || amount === 0) { - return; - } - if (amount < 0) { - amount *= -1; - debit *= -1; - } - oldJournal = getOld($scope.account.LedgerID, $scope.voucher.Journals); - if (!angular.isUndefined(oldJournal)) { - amount = (oldJournal.Debit * oldJournal.Amount) + (debit * amount); - if (amount < 0) { - oldJournal.Debit = -1; - oldJournal.Amount = amount * -1; - } else { - oldJournal.Debit = 1; - oldJournal.Amount = amount; - } - } else { - $scope.voucher.Journals.push({Debit: debit, Amount: amount, Ledger: $scope.account}); - } - delete $scope.account; - delete $scope.amount; - $scope.foAccount = true; - }; - - $scope.removeJournal = function (journal) { - var index = $scope.voucher.Journals.indexOf(journal); - $scope.voucher.Journals.splice(index, 1); - }; - - $scope.$watch('voucher.Journals', function (journals) { - if (!angular.isArray(journals)) { - return; - } - var amount = journals.reduce(function (previousValue, currentValue) { - return previousValue + (currentValue.Amount * currentValue.Debit); - }, 0); - $scope.amount = Math.abs(amount); - }, true); - - $scope.$watch('account', function (account) { - if (!account) { - delete $scope.accBal; - } - else { - Account.balance({id: account.LedgerID, d: $scope.voucher.Date}, function (bal) { - $scope.accBal = bal; - }); - } - }, true); - - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined($scope.perms)) { - return false; - } else if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Journal']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID !== $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.save = function () { - return $scope.voucher.$save({type: 'Journal'}, function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Journal/' + u.VoucherID); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.voucher.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Journal').replace(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.post = function () { - return $scope.voucher.$post(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.modal = function (journal) { - $scope.selectedJournal = journal; - var edit = {}; - angular.copy($scope.selectedJournal, edit); - var modalInstance = $modal.open({ - backdrop: true, - size: 'lg', - templateUrl: '/app/journal/journal-modal.html', - controller: JournalModalController, - resolve: { - edit: function () { - return edit; - } - } - }); - modalInstance.result.then(function (updated) { - if (updated.Ledger.LedgerID !== $scope.selectedJournal.Ledger.LedgerID) { - var oldJournal = getOld(updated.Ledger.LedgerID, $scope.voucher.Journals); - if (!angular.isUndefined(oldJournal)) { - delete $scope.selectedJournal; - return false; - } - } - angular.copy(updated, $scope.selectedJournal); - delete $scope.selectedJournal; - }, function () { - delete $scope.selectedJournal; - } - ); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} - -JournalController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id; - if (angular.isUndefined(id)) { - return Voucher.get({type: 'Journal'}).$promise; - } else { - return Voucher.get({id: id}).$promise; - } - }] -}; diff --git a/brewman/static/app/journal/journal.controller.ts b/brewman/static/app/journal/journal.controller.ts new file mode 100644 index 00000000..65869193 --- /dev/null +++ b/brewman/static/app/journal/journal.controller.ts @@ -0,0 +1,229 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import {JournalModalController} from './journal-modal.controller'; + +export class JournalController { + static $inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'UploadedImageResizer', 'MathSolver', 'Account', 'uibDateParser', 'Messages', 'Credentials']; + _voucher_Date: any; + foAccount: any; + debit: any; + selectedJournal: any; + amount: any; + account: any; + voucher: any; + accBal: any; + + constructor(public $scope, public $location, public asDate, public $modal, public UploadedImageResizer, public MathSolver, public Account, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + this.foAccount = true; + this.debit = "1"; + $scope.$on("fileSelected", (event, args) => { + UploadedImageResizer(args, this.voucher.Files); + }); + $scope.$watch('vm.voucher.Journals', (journals) => { + if (!angular.isArray(journals)) { + return; + } + const amount = journals.reduce(function (previousValue, currentValue) { + return previousValue + (currentValue.Amount * currentValue.Debit); + }, 0); + this.amount = Math.abs(amount); + }, true); + + $scope.$watch('vm.account', (account) => { + if (!account) { + delete this.accBal; + } + else { + Account.balance({id: account.LedgerID, d: this.voucher.Date}, (bal) => { + this.accBal = bal; + }); + } + }, true); + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + getOld(ledgerID, journals) { + return _.find(journals, function (journal) { + return journal.Ledger.LedgerID === ledgerID; + }); + } + + deleteFile(item) { + const index = this.voucher.Files.indexOf(item); + this.voucher.Files.splice(index, 1); + } + + zoomImage(item) { + this.$modal.open({ + templateUrl: '/template/modal/image.html', + controllerAs: 'vmModal', + controller: ['$uibModalInstance', class { + imageUrl: any; + size: any; + + constructor(public $modalInstance) { + this.imageUrl = item.Resized; + this.size = null; + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + } + + add() { + let amount, + oldJournal, + debit = parseInt(this.debit); + + if (!this.account || !this.account.LedgerID) { + return; + } + amount = this.MathSolver(this.amount); + if (Number.isNaN(amount) || amount === 0) { + return; + } + if (amount < 0) { + amount *= -1; + debit *= -1; + } + oldJournal = this.getOld(this.account.LedgerID, this.voucher.Journals); + if (!angular.isUndefined(oldJournal)) { + amount = (oldJournal.Debit * oldJournal.Amount) + (debit * amount); + if (amount < 0) { + oldJournal.Debit = -1; + oldJournal.Amount = amount * -1; + } else { + oldJournal.Debit = 1; + oldJournal.Amount = amount; + } + } else { + this.voucher.Journals.push({Debit: debit, Amount: amount, Ledger: this.account}); + } + delete this.account; + delete this.amount; + this.foAccount = true; + } + + removeJournal(journal) { + const index = this.voucher.Journals.indexOf(journal); + this.voucher.Journals.splice(index, 1); + } + + preventAlteration(voucher) { + if (angular.isUndefined(this.Credentials.Perms)) { + return false; + } else if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Journal']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID !== this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + save() { + return this.voucher.$save({type: 'Journal'}, (u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Journal/' + u.VoucherID); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.voucher.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Journal').replace(); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + post() { + return this.voucher.$post((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + modal(journal) { + this.selectedJournal = journal; + let edit = {}; + angular.copy(this.selectedJournal, edit); + const modalInstance = this.$modal.open({ + backdrop: true, + size: 'lg', + templateUrl: '/app/journal/journal-modal.html', + controllerAs: 'vmModal', + controller: JournalModalController, + resolve: { + edit: function () { + return edit; + } + } + }); + modalInstance.result.then((updated) => { + if (updated.Ledger.LedgerID !== this.selectedJournal.Ledger.LedgerID) { + const oldJournal = this.getOld(updated.Ledger.LedgerID, this.voucher.Journals); + if (!angular.isUndefined(oldJournal)) { + delete this.selectedJournal; + return false; + } + } + angular.copy(updated, this.selectedJournal); + delete this.selectedJournal; + }, () => { + delete this.selectedJournal; + } + ); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controllerAs: 'vmModal', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/journal/journal.html b/brewman/static/app/journal/journal.html index 09757a81..b28aad1d 100644 --- a/brewman/static/app/journal/journal.html +++ b/brewman/static/app/journal/journal.html @@ -7,7 +7,7 @@
@@ -19,26 +19,26 @@
-
- + -

Balance as on Date: {{accBal.Date | accounting}} / {{accBal.Total +

Balance as on Date: {{vm.accBal.Date | accounting}} / {{vm.accBal.Total | accounting}}

+ ng-model="vm.amount" on-return="vm.add()"/> - @@ -56,18 +56,18 @@
- + @@ -80,14 +80,14 @@
- +
-
- - +
+ +
Code
{{item.Code}} {{item.Name}} {{item.Designation}}
{{item.Name}}
    diff --git a/brewman/static/app/group/group-list.resolver.ts b/brewman/static/app/group/group-list.resolver.ts new file mode 100644 index 00000000..4e5ed5e9 --- /dev/null +++ b/brewman/static/app/group/group-list.resolver.ts @@ -0,0 +1,3 @@ +export function GroupListResolver(Group) { + return Group.query({}).$promise; +} diff --git a/brewman/static/app/group/group.component.ts b/brewman/static/app/group/group.component.ts new file mode 100644 index 00000000..84e1ec83 --- /dev/null +++ b/brewman/static/app/group/group.component.ts @@ -0,0 +1,7 @@ +import {GroupController} from './group.controller'; + +export const GroupComponent = { + templateUrl: '/app/group/group-detail.html', + controller: GroupController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/group/group.controller.js b/brewman/static/app/group/group.controller.js deleted file mode 100644 index 0ee2cb10..00000000 --- a/brewman/static/app/group/group.controller.js +++ /dev/null @@ -1,33 +0,0 @@ -angular - .module('overlord') - .controller('GroupController', GroupController); -GroupController.$inject = ['$scope', '$location', 'group']; -function GroupController($scope, $location, group) { - $scope.group = group; - - $scope.save = function () { - $scope.group.$save(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Groups') - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.group.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Groups') - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.foName = true; -} - -GroupController.resolve = { - group: ['$route', 'Group', function ($route, Group) { - var id = $route.current.params.id; - return Group.get({id: id}).$promise; - }] -}; diff --git a/brewman/static/app/group/group.controller.ts b/brewman/static/app/group/group.controller.ts new file mode 100644 index 00000000..f36bf55a --- /dev/null +++ b/brewman/static/app/group/group.controller.ts @@ -0,0 +1,28 @@ +export class GroupController { + static $inject = ['$scope', '$location', 'Messages']; + foName: boolean; + group: any; + + constructor(public $scope, public $location, public Messages) { + this.group = $scope.$parent.res.group; + this.foName = true; + } + + save() { + this.group.$save((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Groups') + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.group.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Groups') + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } +} diff --git a/brewman/static/app/group/group.resolver.ts b/brewman/static/app/group/group.resolver.ts new file mode 100644 index 00000000..771a50df --- /dev/null +++ b/brewman/static/app/group/group.resolver.ts @@ -0,0 +1,4 @@ +export function GroupResolver($route, Group) { + const id = $route.current.params.id; + return Group.get({id: id}).$promise; +} diff --git a/brewman/static/app/group/group.service.ts b/brewman/static/app/group/group.service.ts new file mode 100644 index 00000000..bd3fac45 --- /dev/null +++ b/brewman/static/app/group/group.service.ts @@ -0,0 +1,6 @@ +export function Group($resource) { + return $resource('/api/Group/:id', + {id: '@GroupID'}, { + query: {method: 'GET', params: {list: true}, isArray: true} + }); +} diff --git a/brewman/static/app/home.controller.js b/brewman/static/app/home.controller.js deleted file mode 100644 index b40a64a5..00000000 --- a/brewman/static/app/home.controller.js +++ /dev/null @@ -1,7 +0,0 @@ -angular - .module('overlord') - .controller('HomeController', HomeController); -HomeController.$inject = ['$location']; -function HomeController($location) { -} -HomeController.resolve = {}; \ No newline at end of file diff --git a/brewman/static/app/home/home.component.ts b/brewman/static/app/home/home.component.ts new file mode 100644 index 00000000..dd9bd33b --- /dev/null +++ b/brewman/static/app/home/home.component.ts @@ -0,0 +1,7 @@ +import {HomeController} from "./home.controller"; + +export const HomeComponent = { + templateUrl: '/app/home/home.html', + controller: HomeController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/home/home.controller.ts b/brewman/static/app/home/home.controller.ts new file mode 100644 index 00000000..e7f2dc3c --- /dev/null +++ b/brewman/static/app/home/home.controller.ts @@ -0,0 +1,6 @@ +export class HomeController { + static $inject = ['$location']; + + constructor(public $location) { + } +} diff --git a/brewman/static/app/home.html b/brewman/static/app/home/home.html similarity index 100% rename from brewman/static/app/home.html rename to brewman/static/app/home/home.html diff --git a/brewman/static/app/incentive/incentive-voucher.resolver.ts b/brewman/static/app/incentive/incentive-voucher.resolver.ts new file mode 100644 index 00000000..c116f0d7 --- /dev/null +++ b/brewman/static/app/incentive/incentive-voucher.resolver.ts @@ -0,0 +1,11 @@ +import * as angular from 'angular'; + +export function IncentiveVoucherResolver($route, Voucher) { + const id = $route.current.params.id; + + if (angular.isUndefined(id)) { + return Voucher.get({type: 'Service Charge'}).$promise; + } else { + return Voucher.get({id: id}).$promise; + } +} diff --git a/brewman/static/app/incentive/incentive.component.ts b/brewman/static/app/incentive/incentive.component.ts new file mode 100644 index 00000000..6f4e71d9 --- /dev/null +++ b/brewman/static/app/incentive/incentive.component.ts @@ -0,0 +1,7 @@ +import {IncentiveController} from "./incentive.controller"; + +export const IncentiveComponent = { + templateUrl: '/app/incentive/incentive.html', + controller: IncentiveController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/incentive/incentive.controller.ts b/brewman/static/app/incentive/incentive.controller.ts new file mode 100644 index 00000000..4a2aa80f --- /dev/null +++ b/brewman/static/app/incentive/incentive.controller.ts @@ -0,0 +1,126 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; + +export class IncentiveController { + static $inject = ['$scope', '$location', '$routeParams', 'numberFilter', 'asDateFilter', '$uibModal', 'uibDateParser', 'Messages', 'Credentials']; + _voucher_Date: any; + voucher: any; + + constructor(public $scope, public $location, public $routeParams, public numberFilter, public asDate, public $modal, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + + $scope.$watch('vm.voucher.Date', (newDate, oldDate) => { + const nDate = asDate(newDate), + oDate = asDate(oldDate); + if (nDate !== oDate && !angular.isUndefined(nDate)) { + if (angular.isUndefined($routeParams.id)) { + return this.voucher.$get({type: 'Service Charge', Date: nDate}).$promise; + } + } + }, true); + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + TotalPoints() { + return _(this.voucher.ServiceCharges).map(function (item) { + return item.DaysWorked * Number(item.Points); + }).reduce(function (sum, item) { + return sum + item; + }); + } + + PointValue() { + return Math.round(this.voucher.ServiceCharge * 100 / this.TotalPoints()) / 100; + } + + less(employee) { + if (employee.Points >= 1) { + employee.Points -= 1; + } + } + + more(employee) { + employee.Points += 1; + } + + employeeAmount(employee) { + return Number(employee.Points) * employee.DaysWorked * this.PointValue(); + } + + preventAlteration(voucher) { + if (angular.isUndefined(this.Credentials.Perms)) { + return false; + } else if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Service Charge']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID !== this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + save() { + this.voucher.$save({type: 'Service Charge'}, (u) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/ServiceCharge/' + u.VoucherID); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.voucher.$delete(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/ServiceCharge').replace(); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + post() { + this.voucher.$post((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } +} diff --git a/brewman/static/app/employee/employee-service-charge.html b/brewman/static/app/incentive/incentive.html similarity index 60% rename from brewman/static/app/employee/employee-service-charge.html rename to brewman/static/app/incentive/incentive.html index 55510355..5e4d538a 100644 --- a/brewman/static/app/employee/employee-service-charge.html +++ b/brewman/static/app/incentive/incentive.html @@ -7,7 +7,7 @@
    @@ -19,9 +19,9 @@
    - Total Service Charge: {{voucher.ServiceCharge | number:2}} - Total Points: {{TotalPoints() | number:2}} - Point Value: {{PointValue() | number:2}} + Total Service Charge: {{vm.voucher.ServiceCharge | number:2}} + Total Points: {{vm.TotalPoints() | number:2}} + Point Value: {{vm.PointValue() | number:2}}
    @@ -36,7 +36,7 @@ - + @@ -44,36 +44,36 @@ - +
    {{serviceCharge.Name}} {{serviceCharge.Designation}} {{serviceCharge.Department}}
    - -
    {{employeeAmount(serviceCharge) | number:0}}{{vm.employeeAmount(serviceCharge) | number:0}}
    - - -
    - Created on {{voucher.CreationDate | localTime}} and Last Edited on {{voucher.LastEditDate | localTime}} - by {{voucher.User.Name}}. Posted by {{voucher.Poster}} + Created on {{vm.voucher.CreationDate | localTime}} and Last Edited on {{vm.voucher.LastEditDate | localTime}} + by {{vm.voucher.User.Name}}. Posted by {{vm.voucher.Poster}}
    diff --git a/brewman/static/app/issue/batch.service.ts b/brewman/static/app/issue/batch.service.ts new file mode 100644 index 00000000..28a744aa --- /dev/null +++ b/brewman/static/app/issue/batch.service.ts @@ -0,0 +1,5 @@ +export function Batch ($resource) { + return $resource('/api/Batch', {}, { + autocomplete: {method: 'GET', params: {term: ''}, isArray: true} + }); +} diff --git a/brewman/static/app/issue/issue-grid.resolver.ts b/brewman/static/app/issue/issue-grid.resolver.ts new file mode 100644 index 00000000..22de84a5 --- /dev/null +++ b/brewman/static/app/issue/issue-grid.resolver.ts @@ -0,0 +1,15 @@ +import * as angular from 'angular'; + +export function IssueGridResolver($route, IssueGrid) { + const id = $route.current.params.id, + source = $route.current.params.Source, + destination = $route.current.params.Destination; + + if (!angular.isUndefined(source) && !angular.isUndefined(destination) && !angular.isUndefined(id)) { + return IssueGrid.query({date: id, Source: source, Destination: destination}).$promise; + } else if (angular.isUndefined(source) && angular.isUndefined(destination) && !angular.isUndefined(id)) { + return IssueGrid.query({date: id}).$promise; + } else { + return {}; + } +} diff --git a/brewman/static/app/issue/issue-grid.service.ts b/brewman/static/app/issue/issue-grid.service.ts new file mode 100644 index 00000000..a9aa9984 --- /dev/null +++ b/brewman/static/app/issue/issue-grid.service.ts @@ -0,0 +1,3 @@ +export function IssueGrid($resource) { + return $resource('/api/Issues/Services/:date'); +} diff --git a/brewman/static/app/issue/issue-modal.controller.js b/brewman/static/app/issue/issue-modal.controller.js deleted file mode 100644 index 56b3be64..00000000 --- a/brewman/static/app/issue/issue-modal.controller.js +++ /dev/null @@ -1,22 +0,0 @@ -angular - .module('overlord') - .controller('IssueModalController', IssueModalController); -IssueModalController.$inject = ['$scope', '$uibModalInstance', 'edit', 'Batch']; -function IssueModalController($scope, $modalInstance, edit, Batch) { - $scope.edit = edit; - $scope.ok = function () { - $scope.edit.Product = $scope.edit.Batch.Product; - $scope.edit.Quantity = Number($scope.edit.Quantity); - $scope.edit.Tax = $scope.edit.Batch.Tax; - $scope.edit.Discount = $scope.edit.Batch.Discount; - $scope.edit.Rate = $scope.edit.Batch.Rate; - $scope.edit.Amount = $scope.edit.Quantity * $scope.edit.Rate * (1 + $scope.edit.Tax) * (1 - $scope.edit.Discount); - $modalInstance.close($scope.edit); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - $scope.batches = function ($viewValue) { - return Batch.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} diff --git a/brewman/static/app/issue/issue-modal.controller.ts b/brewman/static/app/issue/issue-modal.controller.ts new file mode 100644 index 00000000..19c7e244 --- /dev/null +++ b/brewman/static/app/issue/issue-modal.controller.ts @@ -0,0 +1,26 @@ +export class IssueModalController { + static $inject = ['$scope', '$uibModalInstance', 'Batch']; + edit:any; + + constructor(public $scope, public $modalInstance, public Batch) { + this.edit = $scope.$resolve.edit; + } + + ok() { + this.edit.Product = this.edit.Batch.Product; + this.edit.Quantity = Number(this.edit.Quantity); + this.edit.Tax = this.edit.Batch.Tax; + this.edit.Discount = this.edit.Batch.Discount; + this.edit.Rate = this.edit.Batch.Rate; + this.edit.Amount = this.edit.Quantity * this.edit.Rate * (1 + this.edit.Tax) * (1 - this.edit.Discount); + this.$modalInstance.close(this.edit); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + + batches($viewValue) { + return this.Batch.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/issue/issue-modal.html b/brewman/static/app/issue/issue-modal.html index 576dd8f3..e5e05ee8 100644 --- a/brewman/static/app/issue/issue-modal.html +++ b/brewman/static/app/issue/issue-modal.html @@ -8,17 +8,17 @@
    -
    - +
    \ No newline at end of file diff --git a/brewman/static/app/issue/issue-voucher.resolver.ts b/brewman/static/app/issue/issue-voucher.resolver.ts new file mode 100644 index 00000000..2522c7de --- /dev/null +++ b/brewman/static/app/issue/issue-voucher.resolver.ts @@ -0,0 +1,15 @@ +import * as angular from 'angular'; + +export function IssueVoucherResolver($route, Voucher) { + const id = $route.current.params.id, + source = $route.current.params.Source, + destination = $route.current.params.Destination; + + if (!angular.isUndefined(source) && !angular.isUndefined(destination) && !angular.isUndefined(id)) { + return Voucher.get({type: 'Issue', Date: id, Source: source, Destination: destination}).$promise; + } else if (angular.isUndefined(source) && angular.isUndefined(destination) && !angular.isUndefined(id)) { + return Voucher.get({id: id}).$promise; + } else { + return Voucher.get({type: 'Issue'}).$promise; + } +} diff --git a/brewman/static/app/issue/issue.component.ts b/brewman/static/app/issue/issue.component.ts new file mode 100644 index 00000000..23d1fc98 --- /dev/null +++ b/brewman/static/app/issue/issue.component.ts @@ -0,0 +1,7 @@ +import {IssueController} from "./issue.controller"; + +export const IssueComponent = { + templateUrl: '/app/issue/issue.html', + controller: IssueController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/issue/issue.controller.js b/brewman/static/app/issue/issue.controller.js deleted file mode 100644 index 4c4b7401..00000000 --- a/brewman/static/app/issue/issue.controller.js +++ /dev/null @@ -1,294 +0,0 @@ -angular - .module('overlord') - .controller('IssueController', IssueController); -IssueController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'voucher', 'costCentres', 'smallGrid', 'IssueGrid', 'Voucher', '$uibModal', 'Batch', 'uibDateParser']; -function IssueController($scope, $routeParams, $location, asDate, voucher, costCentres, smallGrid, IssueGrid, Voucher, $modal, Batch, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.voucher = voucher; - $scope.costCentres = costCentres; - $scope.smallGrid = smallGrid; - - if (angular.isUndefined($routeParams.Source) && angular.isUndefined($routeParams.Destination) && angular.isUndefined($routeParams.id)) { - var date = $scope.voucher.Date; - var source = getDebitCredit($scope.voucher.Journals, -1); - var destination = getDebitCredit($scope.voucher.Journals, 1); - $location.path('/Issue/' + date).search({Source: source, Destination: destination}); - } - - function getOld(productID, inventories) { - return _.find(inventories, function (inventory) { - return inventory.Product.ProductID === productID; - }); - } - - $scope.add = function () { - var oldInventory = getOld($scope.batch.Product.ProductID, $scope.voucher.Inventories), - quantity = Number($scope.quantity), - consumption = (getDebitCredit($scope.voucher.Journals, -1) === '7b845f95-dfef-fa4a-897c-f0baf15284a3'); - - if (!$scope.batch || !$scope.batch.Product.ProductID || !quantity) { - return; - } - - if (!angular.isUndefined(oldInventory) && - oldInventory.Batch.BatchID === $scope.batch.BatchID && - (!consumption || oldInventory.Quantity + quantity <= $scope.batch.QuantityRemaining)) { - oldInventory.Quantity += quantity; - delete $scope.batch; - delete $scope.quantity; - $scope.foBatch = true; - } - - if (angular.isUndefined(oldInventory) && (!consumption || quantity <= $scope.batch.QuantityRemaining)) { - $scope.voucher.Inventories.push( - { - Product: $scope.batch.Product, - Quantity: quantity, - Rate: $scope.batch.Rate, - Tax: $scope.batch.Tax, - Discount: $scope.batch.Discount, - Amount: quantity * $scope.batch.Rate * (1 + $scope.batch.Tax) * (1 - $scope.batch.Discount), - Batch: $scope.batch - }); - delete $scope.batch; - delete $scope.quantity; - $scope.foBatch = true; - } - }; - $scope.removeInventory = function (inventory) { - var index = $scope.voucher.Inventories.indexOf(inventory); - $scope.voucher.Inventories.splice(index, 1); - }; - - $scope.$watch('voucher.Date', function (newDate, oldDate) { - var nDate = asDate(newDate), - oDate = asDate(oldDate); - - - if (nDate !== oDate && !angular.isUndefined(nDate)) { - if (!angular.isUndefined($routeParams.Source) && !angular.isUndefined($routeParams.Destination) && !angular.isUndefined($routeParams.id)) { - $location.path('/Issue/' + nDate).search({ - Source: $routeParams.Source, - Destination: $routeParams.Destination - }); - } else { - $scope.smallGrid = IssueGrid.query({ - date: nDate, - Source: $routeParams.Source, - Destination: $routeParams.Destination - }); - } - } - }, true); - - function getDebitCredit(journals, type) { - for (var i = 0, l = journals.length; i < l; i++) { - if (journals[i].Debit === type) { - return journals[i].CostCentre.CostCentreID; - } - } - } - - $scope.$watch('voucher.Journals', function (newJournals, oldJournals) { - if (angular.isUndefined(newJournals) || angular.equals(newJournals, oldJournals)) { - return; - } - if (!angular.isUndefined(oldJournals)) { - if (getDebitCredit(oldJournals, -1) === getDebitCredit(newJournals, -1) && getDebitCredit(oldJournals, 1) === getDebitCredit(newJournals, 1)) { - return; - } - } - - if (!angular.isUndefined($routeParams.Source) && !angular.isUndefined($routeParams.Destination) && !angular.isUndefined($routeParams.id)) { - $location.path('/Issue/' + $scope.voucher.Date).search({ - Source: getDebitCredit(newJournals, -1), - Destination: getDebitCredit(newJournals, 1) - }); - } else { - $scope.smallGrid = IssueGrid.query({ - date: $scope.voucher.Date, - Source: getDebitCredit(newJournals, -1), - Destination: getDebitCredit(newJournals, 1) - }); - } - }, true); - - $scope.$watch('voucher.Inventories', function (newInventories, oldInventories) { - if (angular.isUndefined(newInventories) || angular.isUndefined(oldInventories)) { - return; - } - var amount = 0; - for (var i = 0, l = newInventories.length; i < l; i++) { - amount += newInventories[i].Amount; - } - for (i = 0, l = $scope.voucher.Journals.length; i < l; i++) { - $scope.voucher.Journals[i].Amount = amount; - } - }, true); - - $scope.resetVoucher = function () { - var date = $scope.voucher.Date; - var source = getDebitCredit($scope.voucher.Journals, -1); - var destination = getDebitCredit($scope.voucher.Journals, 1); - $location.path('/Issue/' + date).search({Source: source, Destination: destination}); - }; - - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Issue']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID != $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.get = function (voucherid) { - $scope.voucher = Voucher.get({id: voucherid}, function (u, putResponseHeaders) { - $location.path('/Issue/' + u.VoucherID); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.save = function () { - $scope.voucher.$save({type: 'Issue'}, function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $scope.redirectOnSave(u); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - return $scope.voucher.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - var date = u.Date; - var source = getDebitCredit(u.Journals, -1); - var destination = getDebitCredit(u.Journals, 1); - $location.path('/Issue/' + date).search({Source: source, Destination: destination}).replace(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.redirectOnSave = function (voucher) { - if (!angular.isUndefined($routeParams.Source) && !angular.isUndefined($routeParams.Destination) && !angular.isUndefined($routeParams.id)) { - Voucher.get({ - type: 'Issue', - Date: $routeParams.id, - Source: $routeParams.Source, - Destination: $routeParams.Destination - }, function (u, putResponseHeaders) { - $scope.voucher = u; - }); - $scope.smallGrid = IssueGrid.query({ - date: $routeParams.id, - Source: $routeParams.Source, - Destination: $routeParams.Destination - }); - } else { - var date = voucher.Date; - var source = getDebitCredit(voucher.Journals, -1); - var destination = getDebitCredit(voucher.Journals, 1); - $location.path('/Issue/' + date).search({Source: source, Destination: destination}); - } - }; - - $scope.modal = function (inventory) { - $scope.selectedInventory = inventory; - var edit = {}; - angular.copy($scope.selectedInventory, edit); - var modalInstance = $modal.open({ - backdrop: true, - size: 'lg', - templateUrl: '/app/issue/issue-modal.html', - controller: IssueModalController, - resolve: { - edit: function () { - return edit; - } - } - }); - modalInstance.result.then(function (updated) { - if (updated.Product.ProductID !== $scope.selectedInventory.Batch.Product.ProductID) { - var oldInventory = getOld(updated.Batch.Product.ProductID, $scope.voucher.Inventories); - if (!angular.isUndefined(oldInventory)) { - delete $scope.selectedInventory; - return false; - } - } - angular.copy(updated, $scope.selectedInventory); - delete $scope.selectedInventory; - }, function () { - delete $scope.selectedInventory; - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - return $scope.delete(); - }); - return modalInstance; - }; - - $scope.batches = function ($viewValue) { - var params = {term: $viewValue, count: 20, date: $scope.voucher.Date}; - return Batch.autocomplete(params).$promise; - }; -} - -IssueController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id, - source = $route.current.params.Source, - destination = $route.current.params.Destination; - - if (!angular.isUndefined(source) && !angular.isUndefined(destination) && !angular.isUndefined(id)) { - return Voucher.get({type: 'Issue', Date: id, Source: source, Destination: destination}).$promise; - } else if (angular.isUndefined(source) && angular.isUndefined(destination) && !angular.isUndefined(id)) { - return Voucher.get({id: id}).$promise; - } else { - return Voucher.get({type: 'Issue'}).$promise; - } - }], - smallGrid: ['$route', 'IssueGrid', function ($route, IssueGrid) { - var id = $route.current.params.id, - source = $route.current.params.Source, - destination = $route.current.params.Destination; - - if (!angular.isUndefined(source) && !angular.isUndefined(destination) && !angular.isUndefined(id)) { - return IssueGrid.query({date: id, Source: source, Destination: destination}).$promise; - } else if (angular.isUndefined(source) && angular.isUndefined(destination) && !angular.isUndefined(id)) { - return IssueGrid.query({date: id}).$promise; - } else { - return []; - } - }], - costCentres: ['CostCentre', function (CostCentre) { - return CostCentre.query({}).$promise; - }] -}; diff --git a/brewman/static/app/issue/issue.controller.ts b/brewman/static/app/issue/issue.controller.ts new file mode 100644 index 00000000..3b53129a --- /dev/null +++ b/brewman/static/app/issue/issue.controller.ts @@ -0,0 +1,283 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import {IssueModalController} from './issue-modal.controller'; + +export class IssueController { + static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'IssueGrid', 'Voucher', '$uibModal', 'Batch', 'uibDateParser', 'Messages', 'Credentials']; + _voucher_Date: any; + foBatch: any; + selectedInventory: any; + quantity: any; + batch: any; + voucher: any; + costCentres: any; + smallGrid: any; + + constructor(public $scope, public $routeParams, public $location, public asDate, public IssueGrid, public Voucher, public $modal, public Batch, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this.costCentres = $scope.$parent.res.costCentres; + this.smallGrid = $scope.$parent.res.smallGrid; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + if (angular.isUndefined(this.$routeParams.Source) && angular.isUndefined(this.$routeParams.Destination) && angular.isUndefined(this.$routeParams.id)) { + const date = this.voucher.Date; + const source = this.getDebitCredit(this.voucher.Journals, -1); + const destination = this.getDebitCredit(this.voucher.Journals, 1); + this.$location.path('/Issue/' + date).search({Source: source, Destination: destination}); + } + $scope.$watch('vm.voucher.Date', (newDate, oldDate) => { + const nDate = asDate(newDate), + oDate = asDate(oldDate); + + if (nDate !== oDate && !angular.isUndefined(nDate)) { + if (!angular.isUndefined(this.$routeParams.Source) && !angular.isUndefined(this.$routeParams.Destination) && !angular.isUndefined(this.$routeParams.id)) { + this.$location.path('/Issue/' + nDate).search({ + Source: this.$routeParams.Source, + Destination: this.$routeParams.Destination + }); + } else { + this.smallGrid = this.IssueGrid.query({ + date: nDate, + Source: this.$routeParams.Source, + Destination: this.$routeParams.Destination + }); + } + } + }, true); + + $scope.$watch('vm.voucher.Journals', (newJournals, oldJournals) => { + if (angular.isUndefined(newJournals) || angular.equals(newJournals, oldJournals)) { + return; + } + if (!angular.isUndefined(oldJournals)) { + if (this.getDebitCredit(oldJournals, -1) === this.getDebitCredit(newJournals, -1) && this.getDebitCredit(oldJournals, 1) === this.getDebitCredit(newJournals, 1)) { + return; + } + } + + if (!angular.isUndefined(this.$routeParams.Source) && !angular.isUndefined(this.$routeParams.Destination) && !angular.isUndefined(this.$routeParams.id)) { + this.$location.path('/Issue/' + this.voucher.Date).search({ + Source: this.getDebitCredit(newJournals, -1), + Destination: this.getDebitCredit(newJournals, 1) + }); + } else { + this.smallGrid = this.IssueGrid.query({ + date: this.voucher.Date, + Source: this.getDebitCredit(newJournals, -1), + Destination: this.getDebitCredit(newJournals, 1) + }); + } + }, true); + + $scope.$watch('vm.voucher.Inventories', (newInventories, oldInventories) => { + if (angular.isUndefined(newInventories) || angular.isUndefined(oldInventories)) { + return; + } + var amount = 0; + for (var i = 0, l = newInventories.length; i < l; i++) { + amount += newInventories[i].Amount; + } + for (i = 0, l = this.voucher.Journals.length; i < l; i++) { + this.voucher.Journals[i].Amount = amount; + } + }, true); + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + getOld(productID, inventories) { + return _.find(inventories, function (inventory) { + return inventory.Product.ProductID === productID; + }); + } + + add() { + const oldInventory = this.getOld(this.batch.Product.ProductID, this.voucher.Inventories), + quantity = Number(this.quantity), + consumption = (this.getDebitCredit(this.voucher.Journals, -1) === '7b845f95-dfef-fa4a-897c-f0baf15284a3'); + + if (!this.batch || !this.batch.Product.ProductID || !quantity) { + return; + } + + if (!angular.isUndefined(oldInventory) && + oldInventory.Batch.BatchID === this.batch.BatchID && + (!consumption || oldInventory.Quantity + quantity <= this.batch.QuantityRemaining)) { + oldInventory.Quantity += quantity; + delete this.batch; + delete this.quantity; + this.foBatch = true; + } + + if (angular.isUndefined(oldInventory) && (!consumption || quantity <= this.batch.QuantityRemaining)) { + this.voucher.Inventories.push( + { + Product: this.batch.Product, + Quantity: quantity, + Rate: this.batch.Rate, + Tax: this.batch.Tax, + Discount: this.batch.Discount, + Amount: quantity * this.batch.Rate * (1 + this.batch.Tax) * (1 - this.batch.Discount), + Batch: this.batch + }); + delete this.batch; + delete this.quantity; + this.foBatch = true; + } + } + + removeInventory(inventory) { + const index = this.voucher.Inventories.indexOf(inventory); + this.voucher.Inventories.splice(index, 1); + } + + getDebitCredit(journals, type) { + for (var i = 0, l = journals.length; i < l; i++) { + if (journals[i].Debit === type) { + return journals[i].CostCentre.CostCentreID; + } + } + } + + resetVoucher() { + const date = this.voucher.Date; + const source = this.getDebitCredit(this.voucher.Journals, -1); + const destination = this.getDebitCredit(this.voucher.Journals, 1); + this.$location.path('/Issue/' + date).search({Source: source, Destination: destination}); + } + + preventAlteration(voucher) { + if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Issue']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID != this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + get(voucherid) { + this.voucher = this.Voucher.get({id: voucherid}, (u, putResponseHeaders) => { + this.$location.path('/Issue/' + u.VoucherID); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + save() { + this.voucher.$save({type: 'Issue'}, (u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.redirectOnSave(u); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + return this.voucher.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + const date = u.Date; + const source = this.getDebitCredit(u.Journals, -1); + const destination = this.getDebitCredit(u.Journals, 1); + this.$location.path('/Issue/' + date).search({Source: source, Destination: destination}).replace(); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + redirectOnSave(voucher) { + if (!angular.isUndefined(this.$routeParams.Source) && !angular.isUndefined(this.$routeParams.Destination) && !angular.isUndefined(this.$routeParams.id)) { + this.Voucher.get({ + type: 'Issue', + Date: this.$routeParams.id, + Source: this.$routeParams.Source, + Destination: this.$routeParams.Destination + }, (u, putResponseHeaders) => { + this.voucher = u; + }); + this.smallGrid = this.IssueGrid.query({ + date: this.$routeParams.id, + Source: this.$routeParams.Source, + Destination: this.$routeParams.Destination + }); + } else { + const date = voucher.Date; + const source = this.getDebitCredit(voucher.Journals, -1); + const destination = this.getDebitCredit(voucher.Journals, 1); + this.$location.path('/Issue/' + date).search({Source: source, Destination: destination}); + } + } + + modal(inventory) { + this.selectedInventory = inventory; + let edit = {}; + angular.copy(this.selectedInventory, edit); + const modalInstance = this.$modal.open({ + backdrop: true, + size: 'lg', + templateUrl: '/app/issue/issue-modal.html', + controllerAs: 'vmModal', + controller: IssueModalController, + resolve: { + edit: function () { + return edit; + } + } + }); + modalInstance.result.then((updated) => { + if (updated.Product.ProductID !== this.selectedInventory.Batch.Product.ProductID) { + let oldInventory = this.getOld(updated.Batch.Product.ProductID, this.voucher.Inventories); + if (!angular.isUndefined(oldInventory)) { + delete this.selectedInventory; + return false; + } + } + angular.copy(updated, this.selectedInventory); + delete this.selectedInventory; + }, () => { + delete this.selectedInventory; + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + return this.delete(); + }); + return modalInstance; + } + + batches($viewValue) { + const params = {term: $viewValue, count: 20, date: this.voucher.Date}; + return this.Batch.autocomplete(params).$promise; + } +} diff --git a/brewman/static/app/issue/issue.html b/brewman/static/app/issue/issue.html index 0f84a10d..13f420fe 100644 --- a/brewman/static/app/issue/issue.html +++ b/brewman/static/app/issue/issue.html @@ -8,7 +8,7 @@
Load
{{item.Amount | currency}} Load
-
+
+ ng-options="l.CostCentreID as l.Name for l in vm.costCentres">
-
+
+ ng-options="l.CostCentreID as l.Name for l in vm.costCentres">
@@ -46,16 +46,16 @@
- +
+ ng-model="vm.quantity" on-return="vm.add()"/> -
@@ -73,7 +73,7 @@
{{inventory.Product.Name}} {{inventory.Batch.Name}} {{inventory.Quantity | number:2}}{{inventory.Amount | currency}}
{{journal.Debit | debit}} {{journal.Ledger.Name}} {{journal.Amount | currency}}
+
@@ -53,9 +53,9 @@ - + @@ -72,15 +72,15 @@ - - - + + +
Date
{{item.Date}} {{item.Name}} {{item.Name}}Closing Balance Closing Balance {{footer.Debit | currency}}{{footer.Credit | currency}}{{footer.Running | accounting}}{{vm.footer.Debit | currency}}{{vm.footer.Credit | currency}}{{vm.footer.Running | accounting}}
-
diff --git a/brewman/static/app/ledger/ledger.resolver.ts b/brewman/static/app/ledger/ledger.resolver.ts new file mode 100644 index 00000000..1f5ae4d7 --- /dev/null +++ b/brewman/static/app/ledger/ledger.resolver.ts @@ -0,0 +1,13 @@ +import * as angular from 'angular'; + +export function LedgerResolver($route, Ledger) { + var id = $route.current.params.id, + startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(id)) { + return Ledger.get({}).$promise; + } else { + return Ledger.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/ledger/ledger.service.ts b/brewman/static/app/ledger/ledger.service.ts new file mode 100644 index 00000000..6b36714b --- /dev/null +++ b/brewman/static/app/ledger/ledger.service.ts @@ -0,0 +1,3 @@ +export function Ledger($resource) { + return $resource('/api/Ledger/:id'); +} diff --git a/brewman/static/app/login/login.component.ts b/brewman/static/app/login/login.component.ts new file mode 100644 index 00000000..7d4faa48 --- /dev/null +++ b/brewman/static/app/login/login.component.ts @@ -0,0 +1,7 @@ +import {LoginController} from "./login.controller"; + +export const LoginComponent = { + templateUrl: '/app/login/login.html', + controller: LoginController, + controllerAs: 'vm' +}; \ No newline at end of file diff --git a/brewman/static/app/login/login.controller.js b/brewman/static/app/login/login.controller.js deleted file mode 100644 index 12254471..00000000 --- a/brewman/static/app/login/login.controller.js +++ /dev/null @@ -1,35 +0,0 @@ -angular - .module('overlord') - .controller('LoginController', LoginController); -LoginController.$inject = ['$scope', '$http', '$location', '$routeParams', '$cookies']; -function LoginController($scope, $http, $location, $routeParams, $cookies) { - $scope.showOTP = false; - $scope.submit = function () { - var data; - if ($scope.showOTP) { - data = {username: $scope.username, password: $scope.password, otp: $scope.otp, ClientName: $scope.name}; - } else { - data = {username: $scope.username, password: $scope.password}; - } - - - $http. - post('/api/login', data). - then(function () { - var came_from = $routeParams.came_from; - if (angular.isUndefined(came_from) || came_from === "" || came_from === "/login" || came_from === "/logout") { - came_from = "/"; - } - $location.url(came_from); - }). - catch(function (data, status, headers, config) { - if (status === 403 && ['Unknown Client', 'OTP not supplied', 'OTP is wrong'].indexOf(data) !== -1) { - $scope.showOTP = true; - $scope.clientID = $cookies.get('ClientID'); - $scope.$apply(); - } - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.foUsername = true; -} diff --git a/brewman/static/app/login/login.controller.ts b/brewman/static/app/login/login.controller.ts new file mode 100644 index 00000000..e2e834ec --- /dev/null +++ b/brewman/static/app/login/login.controller.ts @@ -0,0 +1,41 @@ +import * as angular from 'angular'; + +export class LoginController { + static $inject = ['$scope', '$http', '$location', '$routeParams', '$cookies', 'Messages']; + showOTP: any; + foUsername: any; + username: any; + password: any; + otp: any; + name: any; + clientID: any; + + constructor(public $scope, public $http, public $location, public $routeParams, public $cookies, public Messages) { + this.showOTP = false; + this.foUsername = true; + } + + public submit() { + var data; + if (this.showOTP) { + data = {username: this.username, password: this.password, otp: this.otp, ClientName: this.name}; + } else { + data = {username: this.username, password: this.password}; + } + + this.$http.post('/api/login', data).then(() => { + var came_from = this.$routeParams.came_from; + if (angular.isUndefined(came_from) || came_from === "" || came_from === "/login" || came_from === "/logout") { + came_from = "/"; + } + this.$location.url(came_from); + }).catch((data, status, headers, config) => { + if (status === 403 && ['Unknown Client', 'OTP not supplied', 'OTP is wrong'].indexOf(data) !== -1) { + this.showOTP = true; + this.clientID = this.$cookies.get('ClientID'); + this.$scope.$apply(); + } + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } +} diff --git a/brewman/static/app/login/login.html b/brewman/static/app/login/login.html index 9478c634..8b7e4a0a 100644 --- a/brewman/static/app/login/login.html +++ b/brewman/static/app/login/login.html @@ -5,32 +5,32 @@
- +
-
-

ClientID {{clientID}}

+

ClientID {{vm.clientID}}

-
+
- +
-
+
- +
@@ -42,7 +42,7 @@
- +
diff --git a/brewman/static/app/login/logout.component.ts b/brewman/static/app/login/logout.component.ts new file mode 100644 index 00000000..861379ee --- /dev/null +++ b/brewman/static/app/login/logout.component.ts @@ -0,0 +1,7 @@ +import {LogoutController} from "./logout.controller"; + +export const LogoutComponent = { + templateUrl: '/app/home.html', + controller: LogoutController, + controllerAs: 'vm' +}; diff --git a/brewman/static/app/login/logout.controller.js b/brewman/static/app/login/logout.controller.js deleted file mode 100644 index d9323451..00000000 --- a/brewman/static/app/login/logout.controller.js +++ /dev/null @@ -1,15 +0,0 @@ -angular - .module('overlord') - .controller('LogoutController', LogoutController); -LogoutController.$inject = ['$scope', '$http', '$location']; -function LogoutController($scope, $http, $location) { - $http. - post('/logout'). - then(function () { - $scope.toasts.push({Type: 'Success', Message: 'Logged out'}); - $location.path('/'); - }). - catch(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage.data}); - }); -} diff --git a/brewman/static/app/login/logout.controller.ts b/brewman/static/app/login/logout.controller.ts new file mode 100644 index 00000000..0f5c0016 --- /dev/null +++ b/brewman/static/app/login/logout.controller.ts @@ -0,0 +1,12 @@ +export class LogoutController { + static $inject = ['$scope', '$http', '$location', 'Messages']; + + constructor(public $scope, public $http, public $location, public Messages) { + this.$http.post('/logout').then(() => { + this.Messages.push({Type: 'Success', Message: 'Logged out'}); + this.$location.path('/'); + }).catch((errorMessage) => { + this.Messages.push({Type: 'Danger', Message: errorMessage.data}); + }); + } +} diff --git a/brewman/static/app/net-transactions/net-transactions.component.ts b/brewman/static/app/net-transactions/net-transactions.component.ts new file mode 100644 index 00000000..efe53e52 --- /dev/null +++ b/brewman/static/app/net-transactions/net-transactions.component.ts @@ -0,0 +1,7 @@ +import {NetTransactionsController} from "./net-transactions.controller"; + +export const NetTransactionsComponent = { + templateUrl: '/app/net-transactions/net-transactions.html', + controller: NetTransactionsController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/net-transactions/net-transactions.controller.js b/brewman/static/app/net-transactions/net-transactions.controller.js deleted file mode 100644 index 14aec1f7..00000000 --- a/brewman/static/app/net-transactions/net-transactions.controller.js +++ /dev/null @@ -1,43 +0,0 @@ -angular - .module('overlord') - .controller('NetTransactionsController', NetTransactionsController); -NetTransactionsController.$inject = ['$scope', '$location', 'asDateFilter', 'netTransactions', 'uibDateParser']; -function NetTransactionsController($scope, $location, asDate, netTransactions, dateParser) { - var _info_StartDate = dateParser.parse(netTransactions.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(netTransactions.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = netTransactions; - $scope.show = function () { - $location.path('/NetTransactions').search({ - StartDate: $scope.info.StartDate, - FinishDate: $scope.info.FinishDate - }); - }; - $scope.foDate = true; -} - -NetTransactionsController.resolve = { - netTransactions: ['$route', 'NetTransactions', function ($route, NetTransactions) { - var startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return NetTransactions.get({}).$promise; - } else { - return NetTransactions.get({StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; diff --git a/brewman/static/app/net-transactions/net-transactions.controller.ts b/brewman/static/app/net-transactions/net-transactions.controller.ts new file mode 100644 index 00000000..43d53fe0 --- /dev/null +++ b/brewman/static/app/net-transactions/net-transactions.controller.ts @@ -0,0 +1,39 @@ +export class NetTransactionsController { + static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + _info_StartDate: any; + _info_FinishDate: any; + info: any; + foDate: any; + netTransactions: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.netTransactions = $scope.$parent.res.netTransactions; + this._info_StartDate = dateParser.parse(this.netTransactions.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.netTransactions.FinishDate, "dd-MMM-yyyy"); + this.info = this.netTransactions; + this.foDate = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/NetTransactions').search({ + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }); + } +} diff --git a/brewman/static/app/net-transactions/net-transactions.html b/brewman/static/app/net-transactions/net-transactions.html index 8daee973..b5cd8961 100644 --- a/brewman/static/app/net-transactions/net-transactions.html +++ b/brewman/static/app/net-transactions/net-transactions.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
@@ -38,7 +38,7 @@ - + diff --git a/brewman/static/app/net-transactions/net-transactions.resolver.ts b/brewman/static/app/net-transactions/net-transactions.resolver.ts new file mode 100644 index 00000000..b1ca4bce --- /dev/null +++ b/brewman/static/app/net-transactions/net-transactions.resolver.ts @@ -0,0 +1,12 @@ +import * as angular from 'angular'; + +export function NetTransactionsResolver($route, NetTransactions) { + const startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return NetTransactions.get({}).$promise; + } else { + return NetTransactions.get({StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/net-transactions/net-transactions.service.ts b/brewman/static/app/net-transactions/net-transactions.service.ts new file mode 100644 index 00000000..6b4695a4 --- /dev/null +++ b/brewman/static/app/net-transactions/net-transactions.service.ts @@ -0,0 +1,3 @@ +export function NetTransactions($resource) { + return $resource('/api/NetTransactions'); +} diff --git a/brewman/static/app/overlord.app.js b/brewman/static/app/overlord.app.js deleted file mode 100644 index 53f0f102..00000000 --- a/brewman/static/app/overlord.app.js +++ /dev/null @@ -1,466 +0,0 @@ -'use strict'; - -var overlord = angular.module('overlord', ['overlord.directive', 'overlord.filter', 'overlord.service', 'ngCookies', 'ngRoute', 'ui.bootstrap', 'chieffancypants.loadingBar', 'ngMaterial']) - .config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) { - $routeProvider. - when('/', {templateUrl: '/app/home.html', controller: HomeController, resolve: HomeController.resolve}). - when('/login', {templateUrl: '/app/login/login.html', controller: LoginController}). - when('/logout', {templateUrl: '/app/home.html', controller: LogoutController}). - - when('/Journal', { - templateUrl: '/app/journal/journal.html', - controller: JournalController, - resolve: JournalController.resolve - }). - when('/Journal/:id', { - templateUrl: '/app/journal/journal.html', - controller: JournalController, - resolve: JournalController.resolve - }). - - when('/Payment', { - templateUrl: '/app/payment/payment.html', - controller: PaymentController, - resolve: PaymentController.resolve, - reloadOnSearch: false - }). - when('/Payment/:id', { - templateUrl: '/app/payment/payment.html', - controller: PaymentController, - resolve: PaymentController.resolve, - reloadOnSearch: false - }). - - when('/Receipt', { - templateUrl: '/app/receipt/receipt.html', - controller: ReceiptController, - resolve: ReceiptController.resolve, - reloadOnSearch: false - }). - when('/Receipt/:id', { - templateUrl: '/app/receipt/receipt.html', - controller: ReceiptController, - resolve: ReceiptController.resolve, - reloadOnSearch: false - }). - - when('/Purchase', { - templateUrl: '/app/purchase/purchase.html', - controller: PurchaseController, - resolve: PurchaseController.resolve - }). - when('/Purchase/:id', { - templateUrl: '/app/purchase/purchase.html', - controller: PurchaseController, - resolve: PurchaseController.resolve - }). - - when('/Return', { - templateUrl: '/app/purchase-return/purchase-return.html', - controller: PurchaseReturnController, - resolve: PurchaseReturnController.resolve - }). - when('/Return/:id', { - templateUrl: '/app/purchase-return/purchase-return.html', - controller: PurchaseReturnController, - resolve: PurchaseReturnController.resolve - }). - - when('/Issue', { - templateUrl: '/app/issue/issue.html', - controller: IssueController, - resolve: IssueController.resolve - }). - when('/Issue/:id', { - templateUrl: '/app/issue/issue.html', - controller: IssueController, - resolve: IssueController.resolve - }). - - when('/SalaryDeduction', { - templateUrl: '/app/salary-deduction/salary-deduction.html', - controller: SalaryDeductionController, - resolve: SalaryDeductionController.resolve - }). - when('/SalaryDeduction/:id', { - templateUrl: '/app/salary-deduction/salary-deduction.html', - controller: SalaryDeductionController, - resolve: SalaryDeductionController.resolve - }). - - when('/ServiceCharge', { - templateUrl: '/app/employee/employee-service-charge.html', - controller: ServiceChargeController, - resolve: ServiceChargeController.resolve - }). - when('/ServiceCharge/:id', { - templateUrl: '/app/employee/employee-service-charge.html', - controller: ServiceChargeController, - resolve: ServiceChargeController.resolve - }). - - when('/Ledger', { - templateUrl: '/app/ledger/ledger.html', - controller: LedgerController, - resolve: LedgerController.resolve - }). - when('/Ledger/:id', { - templateUrl: '/app/ledger/ledger.html', - controller: LedgerController, - resolve: LedgerController.resolve - }). - - when('/Reconcile', { - templateUrl: '/app/reconcile/reconcile.html', - controller: ReconcileController, - resolve: ReconcileController.resolve - }). - when('/Reconcile/:id', { - templateUrl: '/app/reconcile/reconcile.html', - controller: ReconcileController, - resolve: ReconcileController.resolve - }). - - when('/ProductLedger', { - templateUrl: '/app/product-ledger/product-ledger.html', - controller: ProductLedgerController, - resolve: ProductLedgerController.resolve - }). - when('/ProductLedger/:id', { - templateUrl: '/app/product-ledger/product-ledger.html', - controller: ProductLedgerController, - resolve: ProductLedgerController.resolve - }). - - when('/CashFlow', { - templateUrl: '/app/cash-flow/cash-flow.html', - controller: CashFlowController, - resolve: CashFlowController.resolve - }). - when('/CashFlow/:id', { - templateUrl: '/app/cash-flow/cash-flow.html', - controller: CashFlowController, - resolve: CashFlowController.resolve - }). - - when('/RawMaterialCost', { - templateUrl: '/app/raw-material-cost/raw-material-cost.html', - controller: RawMaterialCostController, - resolve: RawMaterialCostController.resolve - }). - when('/RawMaterialCost/:id', { - templateUrl: '/app/raw-material-cost/raw-material-cost-detail.html', - controller: RawMaterialCostController, - resolve: RawMaterialCostController.resolve - }). - - when('/Attendance', { - templateUrl: '/app/attendance/attendance.html', - controller: AttendanceController, - resolve: AttendanceController.resolve - }). - when('/Attendance/:date', { - templateUrl: '/app/attendance/attendance.html', - controller: AttendanceController, - resolve: AttendanceController.resolve - }). - - when('/EmployeeAttendance', { - templateUrl: '/app/employee/employee-attendance.html', - controller: EmployeeAttendanceController, - resolve: EmployeeAttendanceController.resolve - }). - when('/EmployeeAttendance/:id', { - templateUrl: '/app/employee/employee-attendance.html', - controller: EmployeeAttendanceController, - resolve: EmployeeAttendanceController.resolve - }). - - when('/Daybook', { - templateUrl: '/app/daybook/daybook.html', - controller: DaybookController, - resolve: DaybookController.resolve - }). - when('/Unposted', { - templateUrl: '/app/unposted/unposted.html', - controller: UnpostedController, - resolve: UnpostedController.resolve - }). - when('/ProfitLoss', { - templateUrl: '/app/profit-loss/profit-loss.html', - controller: ProfitLossController, - resolve: ProfitLossController.resolve - }). - when('/StockMovement', { - templateUrl: '/app/stock-movement/stock-movement.html', - controller: StockMovementController, - resolve: StockMovementController.resolve - }). - when('/NetTransactions', { - templateUrl: '/app/net-transactions/net-transactions.html', - controller: NetTransactionsController, - resolve: NetTransactionsController.resolve - }). - when('/PurchaseEntries', { - templateUrl: '/app/purchase-entries/purchase-entries.html', - controller: PurchaseEntriesController, - resolve: PurchaseEntriesController.resolve - }). - when('/Purchases', { - templateUrl: '/app/purchases/purchases.html', - controller: PurchasesController, - resolve: PurchasesController.resolve - }). - when('/EmployeeFunctions', { - templateUrl: '/app/employee/employee-functions.html', - controller: EmployeeFunctionsController - }). - - when('/BalanceSheet', { - templateUrl: '/app/balance-sheet/balance-sheet.html', - controller: BalanceSheetController, - resolve: BalanceSheetController.resolve - }). - when('/BalanceSheet/:date', { - templateUrl: '/app/balance-sheet/balance-sheet.html', - controller: BalanceSheetController, - resolve: BalanceSheetController.resolve - }). - - when('/TrialBalance', { - templateUrl: '/app/trial-balance/trial-balance.html', - controller: TrialBalanceController, - resolve: TrialBalanceController.resolve - }). - when('/TrialBalance/:date', { - templateUrl: '/app/trial-balance/trial-balance.html', - controller: TrialBalanceController, - resolve: TrialBalanceController.resolve - }). - - when('/ClosingStock', { - templateUrl: '/app/closing-stock/closing-stock.html', - controller: ClosingStockController, - resolve: ClosingStockController.resolve - }). - when('/ClosingStock/:date', { - templateUrl: '/app/closing-stock/closing-stock.html', - controller: ClosingStockController, - resolve: ClosingStockController.resolve - }). - - when('/Accounts', { - templateUrl: '/app/account/account-list.html', - controller: AccountListController, - resolve: AccountListController.resolve, - reloadOnSearch: false - }). - when('/Account', { - templateUrl: '/app/account/account-detail.html', - controller: AccountController, - resolve: AccountController.resolve - }). - when('/Account/:id', { - templateUrl: '/app/account/account-detail.html', - controller: AccountController, - resolve: AccountController.resolve - }). - - when('/Employees', { - templateUrl: '/app/employee/employee-list.html', - controller: EmployeeListController, - resolve: EmployeeListController.resolve, - reloadOnSearch: false - }). - when('/Employee', { - templateUrl: '/app/employee/employee-detail.html', - controller: EmployeeController, - resolve: EmployeeController.resolve - }). - when('/Employee/:id', { - templateUrl: '/app/employee/employee-detail.html', - controller: EmployeeController, - resolve: EmployeeController.resolve - }). - - when('/CostCentres', { - templateUrl: '/app/cost-centre/cost-centre-list.html', - controller: CostCentreListController, - resolve: CostCentreListController.resolve - }). - when('/CostCentre', { - templateUrl: '/app/cost-centre/cost-centre-detail.html', - controller: CostCentreController, - resolve: CostCentreController.resolve - }). - when('/CostCentre/:id', { - templateUrl: '/app/cost-centre/cost-centre-detail.html', - controller: CostCentreController, - resolve: CostCentreController.resolve - }). - - when('/Products', { - templateUrl: '/app/product/product-list.html', - controller: ProductListController, - resolve: ProductListController.resolve, - reloadOnSearch: false - }). - when('/Product', { - templateUrl: '/app/product/product-detail.html', - controller: ProductController, - resolve: ProductController.resolve - }). - when('/Product/:id', { - templateUrl: '/app/product/product-detail.html', - controller: ProductController, - resolve: ProductController.resolve - }). - - when('/Recipes', { - templateUrl: '/app/recipe/recipe-list.html', - controller: RecipeListController, - resolve: RecipeListController.resolve, - reloadOnSearch: false - }). - when('/Recipe', { - templateUrl: '/app/recipe/recipe-detail.html', - controller: RecipeController, - resolve: RecipeController.resolve - }). - when('/Recipe/:id', { - templateUrl: '/app/recipe/recipe-detail.html', - controller: RecipeController, - resolve: RecipeController.resolve - }). - - when('/ProductGroups', { - templateUrl: '/app/product-group/product-group-list.html', - controller: ProductGroupListController, - resolve: ProductGroupListController.resolve - }). - when('/ProductGroup', { - templateUrl: '/app/product-group/product-group-detail.html', - controller: ProductGroupController, - resolve: ProductGroupController.resolve - }). - when('/ProductGroup/:id', { - templateUrl: '/app/product-group/product-group-detail.html', - controller: ProductGroupController, - resolve: ProductGroupController.resolve - }). - - when('/Users', { - templateUrl: '/app/user/user-list.html', - controller: UserListController, - resolve: UserListController.resolve - }). - when('/User', { - templateUrl: '/app/user/user-detail.html', - controller: UserController, - resolve: UserController.resolve - }). - when('/User/:id', { - templateUrl: '/app/user/user-detail.html', - controller: UserController, - resolve: UserController.resolve - }). - - when('/Groups', { - templateUrl: '/app/group/group-list.html', - controller: GroupListController, - resolve: GroupListController.resolve - }). - when('/Group', { - controller: GroupController, - templateUrl: '/app/group/group-detail.html', - resolve: GroupController.resolve - }). - when('/Group/:id', { - templateUrl: '/app/group/group-detail.html', - controller: GroupController, - resolve: GroupController.resolve - }). - - when('/Clients', { - templateUrl: '/app/client/client-list.html', - controller: ClientListController, - resolve: ClientListController.resolve - }). - when('/Client/:id', { - templateUrl: '/app/client/client-detail.html', - controller: ClientController, - resolve: ClientController.resolve - }). - - when('/Settings', { - templateUrl: '/app/settings/settings.html', - controller: SettingsController, - resolve: SettingsController.resolve - }). - - otherwise({templateUrl: '/app/404.html'}); - $locationProvider.html5Mode(true).hashPrefix('!'); - }]) - .config(['$httpProvider', function ($httpProvider) { - $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; - }]) - .config(['$mdDateLocaleProvider', function ($mdDateLocaleProvider) { - $mdDateLocaleProvider.formatDate = function (date) { - return !angular.isUndefined(date) ? moment(date).format('DD-MMM-YYYY') : ""; - }; - $mdDateLocaleProvider.parseDate = function (date) { - return moment(date, 'DD-MMM-YYYY').toDate(); - }; - }]) - .config(['$controllerProvider', function ($controllerProvider) { - $controllerProvider.allowGlobals(); - }]) - .config(['$httpProvider', function ($httpProvider) { - $httpProvider.interceptors.push('responseInterceptor'); - }]) - .factory('responseInterceptor', ['$q', '$rootScope', function ($q, $rootScope) { - return { - response: function (response) { - return response; - }, - responseError: function (response) { - var headers = response.headers(), - isResourceResponse = headers['content-type'] === "application/json; charset=utf-8", - status = response.status; - if (status === 401 && !isResourceResponse) { - $rootScope.$broadcast('loginRequired'); - } - // otherwise - return $q.reject(response); - } - }; - }]); - -overlord.controller('BaseController', ['$rootScope', '$scope', 'Auth', '$location', '$routeParams', function ($rootScope, $scope, Auth, $location, $routeParams) { - $rootScope.$on('loginRequired', function () { - if ($rootScope.auth.isAuthenticated) { - $location.path('/'); - } else { - var came_from = $routeParams.came_from; - if (angular.isUndefined(came_from) && $location.path() !== '/login') { - came_from = $location.url(); - } - $location.path('/login').search({came_from: came_from}); - } - }); - $scope.toasts = []; - $scope.clearToast = function (item) { - var idx = $scope.toasts.indexOf(item); - if (idx !== -1) { - $scope.toasts.splice(idx, 1); - } - }; - - $rootScope.$on("$routeChangeStart", function (event, next, current) { - Auth.get(function (u, putResponseHeaders) { - $rootScope.auth = u; - $rootScope.perms = u.perms; - }); - }); -}]); - diff --git a/brewman/static/app/overlord.app.ts b/brewman/static/app/overlord.app.ts new file mode 100644 index 00000000..c4938cad --- /dev/null +++ b/brewman/static/app/overlord.app.ts @@ -0,0 +1,36 @@ +import * as angular from 'angular'; +import 'ngCookies'; +import 'ngRoute'; +import 'ngResource'; +import 'angular-ui-bootstrap'; +import 'ngMaterial'; +import 'bootstrap'; + +import {registerRoutes} from './overlord.routes'; +import {configureApp} from './overlord.config'; +import {BaseController} from './base.controller'; +import {addServices} from './overlord.services'; +import {addFilters} from './overlord.filters'; +import {addComponents} from './overlord.components'; +import {addDirectives} from "./overlord.directive"; + +export module app { + angular.module('overlord', [ + 'ngCookies', + 'ngRoute', + 'ngResource', + 'ui.bootstrap', + 'ngMaterial' + ]); + angular + .module('overlord') + .controller('BaseController', BaseController); + + registerRoutes(); + configureApp(); + addServices(); + addFilters(); + addComponents(); + addDirectives(); + export var angularModule = app; +} diff --git a/brewman/static/app/overlord.components.ts b/brewman/static/app/overlord.components.ts new file mode 100644 index 00000000..cfa7df7a --- /dev/null +++ b/brewman/static/app/overlord.components.ts @@ -0,0 +1,99 @@ +import * as angular from 'angular'; + +import {AccountComponent} from './account/account.component'; +import {AccountListComponent} from './account/account-list.component'; +import {AttendanceComponent} from './attendance/attendance.component'; +import {BalanceSheetComponent} from "./balance-sheet/balance-sheet.component"; +import {CashFlowComponent} from './cash-flow/cash-flow.component'; +import {ClientComponent} from "./client/client.component"; +import {ClientListComponent} from "./client/client-list.component"; +import {CostCentreComponent} from './cost-centre/cost-centre.component'; +import {CostCentreListComponent} from './cost-centre/cost-centre-list.component'; +import {ClosingStockComponent} from "./closing-stock/closing-stock.component"; +import {DaybookComponent} from './daybook/daybook.component'; +import {EmployeeComponent} from "./employee/employee.component"; +import {EmployeeListComponent} from "./employee/employee-list.component"; +import {EmployeeAttendanceComponent} from "./employee/employee-attendance.component"; +import {LedgerComponent} from './ledger/ledger.component'; +import {EmployeeFunctionsComponent} from "./employee/employee-functions.component"; +import {GroupComponent} from "./group/group.component"; +import {GroupListComponent} from "./group/group-list.component"; +import {IssueComponent} from "./issue/issue.component"; +import {JournalComponent} from "./journal/journal.component"; +import {NetTransactionsComponent} from "./net-transactions/net-transactions.component"; +import {PaymentComponent} from "./payment/payment.component"; +import {ProductComponent} from "./product/product.component"; +import {ProductListComponent} from "./product/product-list.component"; +import {ProductGroupComponent} from "./product-group/product-group.component"; +import {ProductGroupListComponent} from "./product-group/product-group-list.component"; +import {ProductLedgerComponent} from "./product-ledger/product-ledger.component"; +import {ProfitLossComponent} from "./profit-loss/profit-loss.component"; +import {PurchaseComponent} from "./purchase/purchase.component"; +import {PurchaseEntriesComponent} from "./purchase-entries/purchase-entries.component"; +import {PurchaseReturnComponent} from "./purchase-return/purchase-return.component"; +import {PurchasesComponent} from "./purchases/purchases.component"; +import {RawMaterialCostComponent} from "./raw-material-cost/raw-material-cost.component"; +import {ReceiptComponent} from "./receipt/receipt.component"; +import {ReconcileComponent} from "./reconcile/reconcile.component"; +import {SalaryDeductionComponent} from "./salary-deduction/salary-deduction.component"; +import {SettingsComponent} from "./settings/settings.component"; +import {StockMovementComponent} from "./stock-movement/stock-movement.component"; +import {TrialBalanceComponent} from "./trial-balance/trial-balance.component"; +import {UnpostedComponent} from "./unposted/unposted.component"; +import {UserComponent} from "./user/user.component"; +import {UserListComponent} from "./user/user-list.component"; +import {IncentiveComponent} from "./incentive/incentive.component"; +import {HomeComponent} from "./home/home.component"; +import {LoginComponent} from "./login/login.component"; +import {LogoutController} from "./login/logout.controller"; +import {LogoutComponent} from "./login/logout.component"; + +export function addComponents() { + angular.module('overlord') + .component('account', AccountComponent) + .component('accounts', AccountListComponent) + .component('attendance', AttendanceComponent) + .component('balanceSheet', BalanceSheetComponent) + .component('cashFlow', CashFlowComponent) + .component('client', ClientComponent) + .component('clients', ClientListComponent) + .component('costCentre', CostCentreComponent) + .component('costCentres', CostCentreListComponent) + .component('closingStock', ClosingStockComponent) + .component('daybook', DaybookComponent) + .component('employee', EmployeeComponent) + .component('employees', EmployeeListComponent) + .component('employeeAttendance', EmployeeAttendanceComponent) + .component('employeeFunctions', EmployeeFunctionsComponent) + .component('group', GroupComponent) + .component('groups', GroupListComponent) + .component('home', HomeComponent) + .component('issue', IssueComponent) + .component('ledger', LedgerComponent) + .component('incentive', IncentiveComponent) + .component('journal', JournalComponent) + .component('login', LoginComponent) + .component('logout', LogoutComponent) + .component('netTransactions', NetTransactionsComponent) + .component('payment', PaymentComponent) + .component('product', ProductComponent) + .component('products', ProductListComponent) + .component('productGroup', ProductGroupComponent) + .component('productGroups', ProductGroupListComponent) + .component('productLedger', ProductLedgerComponent) + .component('profitLoss', ProfitLossComponent) + .component('purchase', PurchaseComponent) + .component('purchaseEntries', PurchaseEntriesComponent) + .component('purchaseReturn', PurchaseReturnComponent) + .component('purchases', PurchasesComponent) + .component('rawMaterialCost', RawMaterialCostComponent) + .component('receipt', ReceiptComponent) + .component('reconcile', ReconcileComponent) + .component('salaryDeduction', SalaryDeductionComponent) + .component('settings', SettingsComponent) + .component('stockMovement', StockMovementComponent) + .component('trialBalance', TrialBalanceComponent) + .component('unposted', UnpostedComponent) + .component('user', UserComponent) + .component('users', UserListComponent); +} diff --git a/brewman/static/app/overlord.config.ts b/brewman/static/app/overlord.config.ts new file mode 100644 index 00000000..bd63ea73 --- /dev/null +++ b/brewman/static/app/overlord.config.ts @@ -0,0 +1,40 @@ +import * as angular from 'angular'; +import * as moment from 'moment'; + +export function configureApp() { + angular.module('overlord') + .config(['$httpProvider', function ($httpProvider) { + $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; + }]) + .config(['$mdDateLocaleProvider', function ($mdDateLocaleProvider) { + $mdDateLocaleProvider.formatDate = function (date) { + return !angular.isUndefined(date) ? moment(date).format('DD-MMM-YYYY') : ""; + }; + $mdDateLocaleProvider.parseDate = function (date) { + return moment(date, 'DD-MMM-YYYY').toDate(); + }; + }]) + .config(['$httpProvider', function ($httpProvider) { + $httpProvider.interceptors.push('responseInterceptor'); + }]) + .config(['$qProvider', function ($qProvider) { + $qProvider.errorOnUnhandledRejections(true); + }]) + .factory('responseInterceptor', ['$q', '$rootScope', function ($q, $rootScope) { + return { + response: function (response) { + return response; + }, + responseError: function (response) { + var headers = response.headers(), + isResourceResponse = headers['content-type'] === "application/json; charset=utf-8", + status = response.status; + if (status === 401 && !isResourceResponse) { + $rootScope.$broadcast('loginRequired'); + } + // otherwise + return $q.reject(response); + } + }; + }]); +} \ No newline at end of file diff --git a/brewman/static/app/overlord.directive.ts b/brewman/static/app/overlord.directive.ts new file mode 100644 index 00000000..abb08021 --- /dev/null +++ b/brewman/static/app/overlord.directive.ts @@ -0,0 +1,23 @@ +import * as angular from 'angular'; +import {AttendanceSubDirective} from './attendance/attendance-sub.directive'; +import {EmployeeAttendanceSubDirective} from "./employee/employee-attendance-sub.directive"; +import {FocusOn} from "./common/focus-on.directive"; +import {FileUpload} from "./common/file-upload.directive"; +import {TanClick} from "./common/tan-click.directive"; +import {OnReturn} from "./common/on-return.directive"; +import {Keypress} from "./common/keypress.directive"; +import {NgGrowl} from "./common/ng-growl.directive"; +import {Fadey} from "./common/fadey.directive"; + +export function addDirectives() { + angular.module('overlord') + .directive('attendanceSub', AttendanceSubDirective) + .directive('employeeAttendanceSub', EmployeeAttendanceSubDirective) + .directive('focusOn', ['$timeout', '$parse', FocusOn]) + .directive('fileUpload', FileUpload) + .directive('tanClick', ['$parse', '$timeout', TanClick]) + .directive('onReturn', ['$parse', OnReturn]) + .directive('keypress', Keypress) + .directive('ngGrowl', ['growl', '$parse', NgGrowl]) + .directive('fadey', Fadey); +} \ No newline at end of file diff --git a/brewman/static/app/overlord.filters.ts b/brewman/static/app/overlord.filters.ts new file mode 100644 index 00000000..99ad9da0 --- /dev/null +++ b/brewman/static/app/overlord.filters.ts @@ -0,0 +1,26 @@ +import * as angular from 'angular'; + +import {Accounting} from './common/accounting.filter'; +import {AsDate} from './common/as-date.filter'; +import {Clr} from './common/clr.filter'; +import {Debit} from "./common/debit.filter"; +import {LocalTime} from "./common/local-time.filter"; +import {Md} from "./common/md.filter"; +import {Percent} from "./common/percent.filter"; +import {Posted} from "./common/posted.filter"; +import {SaveButtonText} from "./common/saveButtonText.filter"; +import {JournalDebit} from "./common/journal-debit.filter"; + +export function addFilters() { + angular.module('overlord') + .filter('accounting', ['currencyFilter', Accounting]) + .filter('asDate', ['dateFilter', AsDate]) + .filter('clr', Clr) + .filter('debit', Debit) + .filter('localTime', LocalTime) + .filter('md', Md) + .filter('percent', ['numberFilter', Percent]) + .filter('posted', Posted) + .filter('saveButton', SaveButtonText) + .filter('journalDebit', JournalDebit); +} \ No newline at end of file diff --git a/brewman/static/app/overlord.routes.ts b/brewman/static/app/overlord.routes.ts new file mode 100644 index 00000000..572cbef9 --- /dev/null +++ b/brewman/static/app/overlord.routes.ts @@ -0,0 +1,474 @@ +import * as angular from 'angular'; + +import {AccountResolver} from './account/account.resolver'; +import {AccountListResolver} from './account/account-list.resolver'; +import {AccountTypesResolver} from './account/account-types.resolver'; +import {PaymentAccountsResolver} from './account/payment-accounts.resolver'; +import {ReceiptAccountsResolver} from './account/receipt-accounts.resolver'; +import {AttendanceInfoResolver} from './attendance/attendance-info.resolver'; +import {AttendanceTypesResolver} from './attendance/attendance-types.resolver'; +import {BalanceSheetResolver} from './balance-sheet/balance-sheet.resolver'; +import {ClientResolver} from './client/client.resolver'; +import {ClientListResolver} from './client/client-list.resolver'; +import {ClosingStockResolver} from './closing-stock/closing-stock.resolver'; +import {CostCentreResolver} from './cost-centre/cost-centre.resolver'; +import {CostCentreListResolver} from './cost-centre/cost-centre-list.resolver'; +import {DaybookResolver} from './daybook/daybook.resolver'; +import {EmployeeAttendanceInfoResolver} from './employee/employee-attendance-info.resolver'; +import {EmployeeResolver} from './employee/employee.resolver'; +import {EmployeeListResolver} from './employee/employee-list.resolver'; +import {CashFlowResolver} from './cash-flow/cash-flow.resolver'; +import {GroupResolver} from './group/group.resolver'; +import {GroupListResolver} from './group/group-list.resolver'; +import {IssueVoucherResolver} from './issue/issue-voucher.resolver'; +import {IssueGridResolver} from './issue/issue-grid.resolver'; +import {JournalVoucherResolver} from './journal/journal-voucher.resolver'; +import {LedgerResolver} from './ledger/ledger.resolver'; +import {NetTransactionsResolver} from './net-transactions/net-transactions.resolver'; +import {PaymentVoucherResolver} from './payment/payment-voucher.resolver'; +import {ProductLedgerResolver} from './product-ledger/product-ledger.resolver'; +import {ProfitLossResolver} from './profit-loss/profit-loss.resolver'; +import {ProductResolver} from './product/product.resolver'; +import {ProductListResolver} from './product/product-list.resolver'; +import {ProductGroupResolver} from './product-group/product-group.resolver'; +import {ProductGroupListResolver} from './product-group/product-group-list.resolver'; +import {PurchaseVoucherResolver} from './purchase/purchase-voucher.resolver'; +import {PurchaseEntriesResolver} from './purchase-entries/purchase-entries.resolver'; +import {PurchaseReturnVoucherResolver} from './purchase-return/purchase-return-voucher.resolver'; +import {PurchasesResolver} from './purchases/purchases.resolver'; +import {RawMaterialCostResolver} from './raw-material-cost/raw-material-cost.resolver'; +import {ReceiptVoucherResolver} from './receipt/receipt-voucher.resolver'; +import {ReconcileResolver} from './reconcile/reconcile.resolver'; +import {SalaryDeductionVoucherResolver} from './salary-deduction/salary-deduction-voucher.resolver'; +import {StockMovementResolver} from './stock-movement/stock-movement.resolver'; +import {TrialBalanceResolver} from './trial-balance/trial-balance.resolver'; +import {UnpostedResolver} from './unposted/unposted.resolver'; +import {UserResolver} from './user/user.resolver'; +import {UserListResolver} from './user/user-list.resolver'; +import {LockInfoResolver} from './settings/lock-info.resolver'; +import {MaintenanceResolver} from './settings/maintenance.resolver'; +import {IncentiveVoucherResolver} from "./incentive/incentive-voucher.resolver"; + +export function registerRoutes() { + angular.module('overlord') + .config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) { + $routeProvider + .when('/', { + template: '', + }) + .when('/login', { + template: '', + }) + .when('/logout', { + template: '', + }) + .when('/Journal', { + template: '', + resolveAs: 'res', + resolve: {voucher: JournalVoucherResolver} + }) + .when('/Journal/:id', { + template: '', + resolveAs: 'res', + resolve: {voucher: JournalVoucherResolver} + }) + .when('/Payment', { + template: '', + resolveAs: 'res', + resolve: { + voucher: PaymentVoucherResolver, + ledgers: PaymentAccountsResolver + }, + reloadOnSearch: false + }) + .when('/Payment/:id', { + template: '', + resolveAs: 'res', + resolve: { + voucher: PaymentVoucherResolver, + ledgers: PaymentAccountsResolver + }, + reloadOnSearch: false + }) + .when('/Receipt', { + template: '', + resolveAs: 'res', + resolve: { + voucher: ReceiptVoucherResolver, + ledgers: ReceiptAccountsResolver + }, + reloadOnSearch: false + }) + .when('/Receipt/:id', { + template: '', + resolveAs: 'res', + resolve: { + voucher: ReceiptVoucherResolver, + ledgers: ReceiptAccountsResolver + }, + reloadOnSearch: false + }) + .when('/Purchase', { + template: '', + resolveAs: 'res', + resolve: {voucher: PurchaseVoucherResolver} + }) + .when('/Purchase/:id', { + template: '', + resolveAs: 'res', + resolve: {voucher: PurchaseVoucherResolver} + }) + .when('/Return', { + template: '', + resolveAs: 'res', + resolve: {voucher: PurchaseReturnVoucherResolver} + }) + .when('/Return/:id', { + template: '', + resolveAs: 'res', + resolve: {voucher: PurchaseReturnVoucherResolver} + }) + .when('/Issue', { + template: '', + resolveAs: 'res', + resolve: { + voucher: IssueVoucherResolver, + smallGrid: IssueGridResolver, + costCentres: CostCentreListResolver + } + }) + .when('/Issue/:id', { + template: '', + resolveAs: 'res', + resolve: { + voucher: IssueVoucherResolver, + smallGrid: IssueGridResolver, + costCentres: CostCentreListResolver + } + }) + .when('/SalaryDeduction', { + template: '', + resolveAs: 'res', + resolve: {voucher: SalaryDeductionVoucherResolver} + }) + .when('/SalaryDeduction/:id', { + template: '', + resolveAs: 'res', + resolve: {voucher: SalaryDeductionVoucherResolver} + }) + .when('/Incentive', { + template: '', + resolveAs: 'res', + resolve: {voucher: IncentiveVoucherResolver} + }) + .when('/Incentive/:id', { + template: '', + resolveAs: 'res', + resolve: {voucher: IncentiveVoucherResolver} + }) + .when('/Ledger', { + template: '', + resolveAs: 'res', + resolve: {ledger: LedgerResolver} + }) + .when('/Ledger/:id', { + template: '', + resolveAs: 'res', + resolve: {ledger: LedgerResolver} + }) + .when('/Reconcile', { + template: '', + resolveAs: 'res', + resolve: {reconcile: ReconcileResolver} + }) + .when('/Reconcile/:id', { + template: '', + resolveAs: 'res', + resolve: {reconcile: ReconcileResolver} + }) + .when('/ProductLedger', { + template: '', + resolveAs: 'res', + resolve: {productLedger: ProductLedgerResolver} + }) + .when('/ProductLedger/:id', { + template: '', + resolveAs: 'res', + resolve: {productLedger: ProductLedgerResolver} + }) + .when('/CashFlow', { + template: '', + resolveAs: 'res', + resolve: {cashFlow: CashFlowResolver} + }) + .when('/CashFlow/:id', { + template: '', + resolveAs: 'res', + resolve: {cashFlow: CashFlowResolver} + }) + .when('/RawMaterialCost', { + template: '', + resolveAs: 'res', + resolve: {rawMaterialCost: RawMaterialCostResolver} + }) + .when('/RawMaterialCost/:id', { + template: '', + resolveAs: 'res', + resolve: {rawMaterialCost: RawMaterialCostResolver} + }) + .when('/Attendance', { + template: '', + resolveAs: 'res', + resolve: { + info: AttendanceInfoResolver, + attendanceTypes: AttendanceTypesResolver + } + }) + .when('/Attendance/:date', { + template: '', + resolveAs: 'res', + resolve: { + info: AttendanceInfoResolver, + attendanceTypes: AttendanceTypesResolver + } + }) + .when('/EmployeeAttendance', { + template: '', + resolveAs: 'res', + resolve: { + info: EmployeeAttendanceInfoResolver, + attendanceTypes: AttendanceTypesResolver + } + }) + .when('/EmployeeAttendance/:id', { + template: '', + resolveAs: 'res', + resolve: { + info: EmployeeAttendanceInfoResolver, + attendanceTypes: AttendanceTypesResolver + } + }) + .when('/Daybook', { + template: '', + resolveAs: 'res', + resolve: {info: DaybookResolver} + }) + .when('/Unposted', { + template: '', + resolveAs: 'res', + resolve: {info: UnpostedResolver} + }) + .when('/ProfitLoss', { + template: '', + resolveAs: 'res', + resolve: {profit_loss: ProfitLossResolver} + }) + .when('/StockMovement', { + template: '', + resolveAs: 'res', + resolve: {stockMovement: StockMovementResolver} + }) + .when('/NetTransactions', { + template: '', + resolveAs: 'res', + resolve: {netTransactions: NetTransactionsResolver} + }) + .when('/PurchaseEntries', { + template: '', + resolveAs: 'res', + resolve: {purchaseEntries: PurchaseEntriesResolver} + }) + .when('/Purchases', { + template: '', + resolveAs: 'res', + resolve: {purchases: PurchasesResolver} + }) + .when('/EmployeeFunctions', { + template: '' + }) + .when('/BalanceSheet', { + template: '', + resolveAs: 'res', + resolve: {info: BalanceSheetResolver} + }) + .when('/BalanceSheet/:date', { + template: '', + resolveAs: 'res', + resolve: {info: BalanceSheetResolver} + }) + .when('/TrialBalance', { + template: '', + resolveAs: 'res', + resolve: {trialBalance: TrialBalanceResolver} + }) + .when('/TrialBalance/:date', { + template: '', + resolveAs: 'res', + resolve: {trialBalance: TrialBalanceResolver} + }) + .when('/ClosingStock', { + template: '', + resolveAs: 'res', + resolve: {info: ClosingStockResolver} + }) + .when('/ClosingStock/:date', { + template: '', + resolveAs: 'res', + resolve: {info: ClosingStockResolver} + }) + .when('/Ledger', { + template: '', + resolveAs: 'res', + resolve: {ledger: LedgerResolver} + }) + .when('/Accounts', { + template: '', + resolveAs: 'res', + resolve: { + accounts: AccountListResolver + }, + reloadOnSearch: false + }) + .when('/Account', { + template: '', + resolveAs: 'res', + resolve: { + account: AccountResolver, + accountTypes: AccountTypesResolver, + costCentres: CostCentreListResolver + } + }) + .when('/Account/:id', { + template: '', + resolveAs: 'res', + resolve: { + account: AccountResolver, + accountTypes: AccountTypesResolver, + costCentres: CostCentreListResolver + } + }) + .when('/Employees', { + template: '', + resolveAs: 'res', + resolve: {employees: EmployeeListResolver}, + reloadOnSearch: false + }) + .when('/Employee', { + template: '', + resolveAs: 'res', + resolve: { + employee: EmployeeResolver, + costCentres: CostCentreListResolver + } + }) + .when('/Employee/:id', { + template: '', + resolveAs: 'res', + resolve: { + employee: EmployeeResolver, + costCentres: CostCentreListResolver + } + }) + .when('/CostCentres', { + template: '', + resolveAs: 'res', + resolve: {costCentres: CostCentreListResolver} + }) + .when('/CostCentre', { + template: '', + resolveAs: 'res', + resolve: {costCentre: CostCentreResolver} + }) + .when('/CostCentre/:id', { + template: '', + resolveAs: 'res', + resolve: {costCentre: CostCentreResolver} + }) + .when('/Products', { + template: '', + resolveAs: 'res', + resolve: {products: ProductListResolver}, + reloadOnSearch: false + }) + .when('/Product', { + template: '', + resolveAs: 'res', + resolve: { + product: ProductResolver, + productGroups: ProductGroupListResolver + } + }) + .when('/Product/:id', { + template: '', + resolveAs: 'res', + resolve: { + product: ProductResolver, + productGroups: ProductGroupListResolver + } + }) + .when('/ProductGroups', { + template: '', + resolveAs: 'res', + resolve: {productGroups: ProductGroupListResolver} + }) + .when('/ProductGroup', { + template: '', + resolveAs: 'res', + resolve: {productGroup: ProductGroupResolver} + }) + .when('/ProductGroup/:id', { + template: '', + resolveAs: 'res', + resolve: {productGroup: ProductGroupResolver} + }) + .when('/Users', { + template: '', + resolveAs: 'res', + resolve: {users: UserListResolver} + }) + .when('/User', { + template: '', + resolveAs: 'res', + resolve: {user: UserResolver} + }) + .when('/User/:id', { + template: '', + resolveAs: 'res', + resolve: {user: UserResolver} + }) + .when('/Groups', { + template: '', + resolveAs: 'res', + resolve: {groups: GroupListResolver} + }) + .when('/Group', { + template: '', + resolveAs: 'res', + resolve: {group: GroupResolver} + }) + .when('/Group/:id', { + template: '', + resolveAs: 'res', + resolve: {group: GroupResolver} + }) + .when('/Clients', { + template: '', + resolveAs: 'res', + resolve: {clients: ClientListResolver} + }) + .when('/Client/:id', { + template: '', + resolveAs: 'res', + resolve: {client: ClientResolver} + }) + .when('/Settings', { + template: '', + resolveAs: 'res', + resolve: { + lockInfo: LockInfoResolver, + maintenance: MaintenanceResolver + } + }).otherwise({templateUrl: '/app/404.html'}); + $locationProvider.html5Mode(true).hashPrefix('!'); + }]) +} \ No newline at end of file diff --git a/brewman/static/app/overlord.services.ts b/brewman/static/app/overlord.services.ts new file mode 100644 index 00000000..03b6fc82 --- /dev/null +++ b/brewman/static/app/overlord.services.ts @@ -0,0 +1,84 @@ +import * as angular from 'angular'; + +import {Account} from './account/account.service'; +import {AccountType} from './account/account-type.service'; +import {Attendance} from './attendance/attendance.service'; +import {AttendanceTypes} from './attendance/attendance-types.service'; +import {BalanceSheet} from './balance-sheet/balance-sheet.service'; +import {CashFlow} from "./cash-flow/cash-flow.service"; +import {Client} from "./client/client.service"; +import {Auth} from './common/auth.service'; +import {Tokenizer} from './common/tokenizer.service'; +import {Voucher} from "./common/voucher.service"; +import {CostCentre} from './cost-centre/cost-centre.service'; +import {ClosingStock} from "./closing-stock/closing-stock.service"; +import {Daybook} from './daybook/daybook.service'; +import {Employee} from "./employee/employee.service"; +import {EmployeeAttendance} from "./employee/employee-attendance.service"; +import {Group} from "./group/group.service"; +import {Ledger} from './ledger/ledger.service'; +import {IssueGrid} from "./issue/issue-grid.service"; +import {Batch} from "./issue/batch.service"; +import {Recipe} from "./recipe/recipe.service"; +import {RawMaterialCost} from "./raw-material-cost/raw-material-cost.service"; +import {Reconcile} from "./reconcile/reconcile.service"; +import {ProductLedger} from "./product-ledger/product-ledger.service"; +import {User} from "./user/user.service"; +import {ReaderPromise} from "./common/reader-promise.service"; +import {UploadedImageResizer} from "./common/upload-image-resizer.service"; +import {NetTransactions} from "./net-transactions/net-transactions.service"; +import {MathSolver} from "./common/math-solver.service"; +import {Product} from "./product/product.service"; +import {ProductGroup} from "./product-group/product-group.service"; +import {ProfitLoss} from "./profit-loss/profit-loss.service"; +import {PurchaseEntries} from "./purchase-entries/purchase-entries.service"; +import {Purchases} from "./purchases/purchases.service"; +import {StockMovement} from "./stock-movement/stock-movement.service"; +import {TrialBalance} from "./trial-balance/trial-balance.service"; +import {Unposted} from "./unposted/unposted.service"; +import {Growl} from "./common/growl.service"; +import {Messages} from "./common/message.service"; +import {Credentials} from "./common/credentials.service"; + +export function addServices() { + angular.module('overlord') + .factory('Account', ['$resource', Account]) + .factory('AccountType', ['$resource', AccountType]) + .factory('Attendance', ['$resource', Attendance]) + .factory('AttendanceTypes', ['$resource', AttendanceTypes]) + .factory('BalanceSheet', ['$resource', BalanceSheet]) + .factory('CashFlow', ['$resource', CashFlow]) + .factory('Client', ['$resource', Client]) + .factory('Auth', ['$resource', Auth]) + .factory('Tokenizer', ['$filter', Tokenizer]) + .factory('CostCentre', ['$resource', CostCentre]) + .factory('ClosingStock', ['$resource', ClosingStock]) + .factory('Daybook', ['$resource', Daybook]) + .factory('Employee', ['$resource', Employee]) + .factory('EmployeeAttendance', ['$resource', EmployeeAttendance]) + .factory('Group', ['$resource', Group]) + .factory('IssueGrid', ['$resource', IssueGrid]) + .factory('Batch', ['$resource', Batch]) + .factory('Voucher', ['$resource', Voucher]) + .factory('Ledger', ['$resource', Ledger]) + .factory('Recipe', ['$resource', Recipe]) + .factory('RawMaterialCost', ['$resource', RawMaterialCost]) + .factory('Reconcile', ['$resource', Reconcile]) + .factory('ProductLedger', ['$resource', ProductLedger]) + .factory('User', ['$resource', User]) + .factory("ReaderPromise", ["$q", ReaderPromise]) + .factory("UploadedImageResizer", ["$q", "ReaderPromise", UploadedImageResizer]) + .factory('NetTransactions', ['$resource', NetTransactions]) + .factory("MathSolver", MathSolver) + .factory('Product', ['$resource', Product]) + .factory('ProductGroup', ['$resource', ProductGroup]) + .factory('ProfitLoss', ['$resource', ProfitLoss]) + .factory('PurchaseEntries', ['$resource', PurchaseEntries]) + .factory('Purchases', ['$resource', Purchases]) + .factory('StockMovement', ['$resource', StockMovement]) + .factory('TrialBalance', ['$resource', TrialBalance]) + .factory('Unposted', ['$resource', Unposted]) + .factory('Messages', Messages) + .factory('Credentials', Credentials) + .factory('growl', ['$http', '$compile', '$timeout', Growl]); +} diff --git a/brewman/static/app/payment/payment-modal.controller.js b/brewman/static/app/payment/payment-modal.controller.js deleted file mode 100644 index 6b3f2f0c..00000000 --- a/brewman/static/app/payment/payment-modal.controller.js +++ /dev/null @@ -1,17 +0,0 @@ -angular - .module('overlord') - .controller('PaymentModalController', PaymentModalController); -PaymentModalController.$inject = ['$scope', '$uibModalInstance', 'mathSolver', 'edit', 'Account']; -function PaymentModalController($scope, $modalInstance, mathSolver, edit, Account) { - $scope.edit = edit; - $scope.ok = function () { - $scope.edit.Amount = mathSolver($scope.edit.Amount); - $modalInstance.close($scope.edit); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} diff --git a/brewman/static/app/payment/payment-modal.controller.ts b/brewman/static/app/payment/payment-modal.controller.ts new file mode 100644 index 00000000..8b874438 --- /dev/null +++ b/brewman/static/app/payment/payment-modal.controller.ts @@ -0,0 +1,21 @@ +export class PaymentModalController { + static $inject = ['$scope', '$uibModalInstance', 'MathSolver', 'Account']; + edit:any; + + constructor(public $scope, public $modalInstance, public MathSolver, public Account) { + this.edit = $scope.$resolve.edit; + } + + ok() { + this.edit.Amount = this.MathSolver(this.edit.Amount); + this.$modalInstance.close(this.edit); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/payment/payment-modal.html b/brewman/static/app/payment/payment-modal.html index 025ae166..1e5e2442 100644 --- a/brewman/static/app/payment/payment-modal.html +++ b/brewman/static/app/payment/payment-modal.html @@ -8,20 +8,20 @@
-
+ ng-model="vmModal.edit.Amount"/>
diff --git a/brewman/static/app/payment/payment-voucher.resolver.ts b/brewman/static/app/payment/payment-voucher.resolver.ts new file mode 100644 index 00000000..8e19e010 --- /dev/null +++ b/brewman/static/app/payment/payment-voucher.resolver.ts @@ -0,0 +1,16 @@ +import * as angular from 'angular'; + +export function PaymentVoucherResolver($route, Voucher) { + const id = $route.current.params.id, + account = $route.current.params.a; + + if (angular.isUndefined(id)) { + let options = {type: 'Payment'}; + if (!angular.isUndefined(account)) { + options['a'] = account; + } + return Voucher.get(options).$promise; + } else { + return Voucher.get({id: id}).$promise; + } +} diff --git a/brewman/static/app/payment/payment.component.ts b/brewman/static/app/payment/payment.component.ts new file mode 100644 index 00000000..412f7b9c --- /dev/null +++ b/brewman/static/app/payment/payment.component.ts @@ -0,0 +1,7 @@ +import {PaymentController} from "./payment.controller"; + +export const PaymentComponent = { + templateUrl: '/app/payment/payment.html', + controller: PaymentController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/payment/payment.controller.js b/brewman/static/app/payment/payment.controller.js deleted file mode 100644 index 666dcc09..00000000 --- a/brewman/static/app/payment/payment.controller.js +++ /dev/null @@ -1,216 +0,0 @@ -angular - .module('overlord') - .controller('PaymentController', PaymentController); -PaymentController.$inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'uploadedImageResizer', 'mathSolver', 'voucher', 'ledgers', 'Account', 'uibDateParser']; -function PaymentController($scope, $location, asDate, $modal, uploadedImageResizer, mathSolver, voucher, ledgers, Account, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.foAccount = true; - - $scope.voucher = voucher; - $scope.ledgers = ledgers; - function getOld(ledgerID, journals) { - return _.find(journals, function (journal) { - return journal.Ledger.LedgerID === ledgerID; - }); - } - - $scope.$on("fileSelected", function (event, args) { - uploadedImageResizer(args, $scope.voucher.Files); - }); - - - $scope.deleteFile = function (item) { - var index = $scope.voucher.Files.indexOf(item); - $scope.voucher.Files.splice(index, 1); - }; - - $scope.zoomImage = function (item) { - $modal.open({ - templateUrl: '/template/modal/image.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.imageUrl = item.Resized; - $scope.size = null; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - }; - - $scope.add = function () { - var amount, - oldJournal; - if (!$scope.account || !$scope.account.LedgerID) { - return; - } - amount = mathSolver($scope.amount); - if (Number.isNaN(amount) || amount <= 0) { - return; - } - oldJournal = getOld($scope.account.LedgerID, $scope.voucher.Journals); - if (angular.isUndefined(oldJournal)) { - $scope.voucher.Journals.push({Debit: 1, Amount: amount, Ledger: $scope.account}); - } else { - if (oldJournal.Debit === 1) { - oldJournal.Amount += amount; - } else { - return; - } - } - delete $scope.account; - delete $scope.amount; - $scope.foAccount = true; - }; - - $scope.removeJournal = function (journal) { - var index = $scope.voucher.Journals.indexOf(journal); - $scope.voucher.Journals.splice(index, 1); - }; - - $scope.$watch('voucher.Journals', function (journals, oldValue) { - var amount = _.chain(journals) - .filter({'Debit': 1}) - .reduce(function (sum, item) { - return item.Amount + sum; - }, 0).value(); - - var j = _.find(journals, {'Debit': -1}); - j.Amount = amount; - if (_.find(oldValue, {'Debit': -1}).Ledger.LedgerID !== j.Ledger.LedgerID) { - $location.search({a: j.Ledger.LedgerID}).replace(); - } - }, true); - - $scope.$watch('account', function (account) { - if (!account) { - delete $scope.accBal; - } - else { - Account.balance({id: account.LedgerID, d: $scope.voucher.Date}, function (bal) { - $scope.accBal = bal; - }); - } - }, true); - - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined($scope.perms)) { - return false; - } else if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Payment']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID != $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.save = function () { - return $scope.voucher.$save({type: 'Payment'}, function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Payment/' + u.VoucherID); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.voucher.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Payment').replace(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.post = function () { - return $scope.voucher.$post(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.modal = function (journal) { - $scope.selectedJournal = journal; - var edit = {}; - angular.copy($scope.selectedJournal, edit); - var modalInstance = $modal.open({ - backdrop: true, - size: 'lg', - templateUrl: '/app/payment/payment-modal.html', - controller: PaymentModalController, - resolve: { - edit: function () { - return edit; - } - } - }); - modalInstance.result.then(function (updated) { - if (updated.Ledger.LedgerID !== $scope.selectedJournal.Ledger.LedgerID) { - var oldJournal = getOld(updated.Ledger.LedgerID, $scope.voucher.Journals); - if (!angular.isUndefined(oldJournal)) { - delete $scope.selectedJournal; - return false; - } - } - angular.copy(updated, $scope.selectedJournal); - delete $scope.selectedJournal; - }, function () { - delete $scope.selectedJournal; - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} - -PaymentController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id, - account = $route.current.params.a; - - if (angular.isUndefined(id)) { - var options = {type: 'Payment'}; - if (!angular.isUndefined(account)) { - options.a = account; - } - return Voucher.get(options).$promise; - } else { - return Voucher.get({id: id}).$promise; - } - }], - ledgers: ['Account', function (Account) { - return Account.autocomplete({term: '', type: 1}).$promise; - }] -}; diff --git a/brewman/static/app/payment/payment.controller.ts b/brewman/static/app/payment/payment.controller.ts new file mode 100644 index 00000000..6a9b0b1b --- /dev/null +++ b/brewman/static/app/payment/payment.controller.ts @@ -0,0 +1,222 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import {PaymentModalController} from './payment-modal.controller'; + +export class PaymentController { + static $inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'UploadedImageResizer', 'MathSolver', 'Account', 'uibDateParser', 'Messages', 'Credentials']; + _voucher_Date: any; + foAccount: any; + selectedJournal: any; + amount: any; + accBal: any; + account: any; + voucher: any; + ledgers: any; + + constructor(public $scope, public $location, public asDate, public $modal, public UploadedImageResizer, public MathSolver, public Account, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this.ledgers = $scope.$parent.res.ledgers; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + this.foAccount = true; + $scope.$on("fileSelected", (event, args) => { + UploadedImageResizer(args, this.voucher.Files); + }); + $scope.$watch('vm.voucher.Journals', (journals, oldValue) => { + const amount = _.chain(journals) + .filter({'Debit': 1}) + .reduce(function (sum, item) { + return item.Amount + sum; + }, 0).value(); + + const j = _.find(journals, {'Debit': -1}); + j.Amount = amount; + if (_.find(oldValue, {'Debit': -1}).Ledger.LedgerID !== j.Ledger.LedgerID) { + $location.search({a: j.Ledger.LedgerID}).replace(); + } + }, true); + + $scope.$watch('vm.account', (account) => { + if (!account) { + delete this.accBal; + } + else { + Account.balance({id: account.LedgerID, d: this.voucher.Date}, (bal) => { + this.accBal = bal; + }); + } + }, true); + + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + getOld(ledgerID, journals) { + return _.find(journals, function (journal) { + return journal.Ledger.LedgerID === ledgerID; + }); + } + + deleteFile(item) { + const index = this.voucher.Files.indexOf(item); + this.voucher.Files.splice(index, 1); + } + + zoomImage(item) { + this.$modal.open({ + templateUrl: '/template/modal/image.html', + controller: ['$uibModalInstance', class { + imageUrl: any; + size: any; + + constructor(public $modalInstance) { + this.imageUrl = item.Resized; + this.size = null; + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + } + + add() { + let amount, + oldJournal; + if (!this.account || !this.account.LedgerID) { + return; + } + amount = this.MathSolver(this.amount); + if (Number.isNaN(amount) || amount <= 0) { + return; + } + oldJournal = this.getOld(this.account.LedgerID, this.voucher.Journals); + if (angular.isUndefined(oldJournal)) { + this.voucher.Journals.push({Debit: 1, Amount: amount, Ledger: this.account}); + } else { + if (oldJournal.Debit === 1) { + oldJournal.Amount += amount; + } else { + return; + } + } + delete this.account; + delete this.amount; + this.foAccount = true; + } + + removeJournal(journal) { + const index = this.voucher.Journals.indexOf(journal); + this.voucher.Journals.splice(index, 1); + } + + preventAlteration(voucher) { + if (angular.isUndefined(this.Credentials.Perms)) { + return false; + } else if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Payment']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID != this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + save() { + return this.voucher.$save({type: 'Payment'}, (u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Payment/' + u.VoucherID); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.voucher.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Payment').replace(); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + post() { + return this.voucher.$post((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + modal(journal) { + this.selectedJournal = journal; + let edit = {}; + angular.copy(this.selectedJournal, edit); + const modalInstance = this.$modal.open({ + backdrop: true, + size: 'lg', + templateUrl: '/app/payment/payment-modal.html', + controllerAs: 'vmModal', + controller: PaymentModalController, + resolve: { + edit: function () { + return edit; + } + } + }); + modalInstance.result.then((updated) => { + if (updated.Ledger.LedgerID !== this.selectedJournal.Ledger.LedgerID) { + const oldJournal = this.getOld(updated.Ledger.LedgerID, this.voucher.Journals); + if (!angular.isUndefined(oldJournal)) { + delete this.selectedJournal; + return false; + } + } + angular.copy(updated, this.selectedJournal); + delete this.selectedJournal; + }, () => { + delete this.selectedJournal; + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/payment/payment.html b/brewman/static/app/payment/payment.html index cdd2d6e2..b85291d8 100644 --- a/brewman/static/app/payment/payment.html +++ b/brewman/static/app/payment/payment.html @@ -7,7 +7,7 @@
@@ -15,10 +15,10 @@
-
+
@@ -29,20 +29,20 @@
- + -

Balance as on Date: {{accBal.Date | accounting}} / {{accBal.Total +

Balance as on Date: {{vm.accBal.Date | accounting}} / {{vm.accBal.Total | accounting}}

+ ng-model="vm.amount" on-return="vm.add()"/> -
@@ -57,17 +57,17 @@
- + @@ -80,14 +80,14 @@
- +
-
- - +
+ +
- +
diff --git a/brewman/static/app/product-group/product-group-list.component.ts b/brewman/static/app/product-group/product-group-list.component.ts new file mode 100644 index 00000000..c2d166e5 --- /dev/null +++ b/brewman/static/app/product-group/product-group-list.component.ts @@ -0,0 +1,7 @@ +import {ProductGroupListController} from "./product-group-list.controller"; + +export const ProductGroupListComponent = { + templateUrl: '/app/product-group/product-group-list.html', + controller: ProductGroupListController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/product-group/product-group-list.controller.js b/brewman/static/app/product-group/product-group-list.controller.js deleted file mode 100644 index 43740293..00000000 --- a/brewman/static/app/product-group/product-group-list.controller.js +++ /dev/null @@ -1,13 +0,0 @@ -angular - .module('overlord') - .controller('ProductGroupListController', ProductGroupListController); -ProductGroupListController.$inject = ['$scope', 'productGroups']; -function ProductGroupListController($scope, productGroups) { - $scope.info = productGroups; -} - -ProductGroupListController.resolve = { - productGroups: ['ProductGroup', function (ProductGroup) { - return ProductGroup.query({}).$promise; - }] -}; diff --git a/brewman/static/app/product-group/product-group-list.controller.ts b/brewman/static/app/product-group/product-group-list.controller.ts new file mode 100644 index 00000000..7ce852a5 --- /dev/null +++ b/brewman/static/app/product-group/product-group-list.controller.ts @@ -0,0 +1,10 @@ +export class ProductGroupListController { + static $inject = ['$scope']; + info: any; + productGroups: any; + + constructor(public $scope) { + this.productGroups = $scope.$parent.res.productGroups; + this.info = this.productGroups; + } +} diff --git a/brewman/static/app/product-group/product-group-list.html b/brewman/static/app/product-group/product-group-list.html index 9757b71a..a7c4b6d7 100644 --- a/brewman/static/app/product-group/product-group-list.html +++ b/brewman/static/app/product-group/product-group-list.html @@ -6,7 +6,7 @@
- + diff --git a/brewman/static/app/product-group/product-group-list.resolver.ts b/brewman/static/app/product-group/product-group-list.resolver.ts new file mode 100644 index 00000000..e7c9da23 --- /dev/null +++ b/brewman/static/app/product-group/product-group-list.resolver.ts @@ -0,0 +1,3 @@ +export function ProductGroupListResolver(ProductGroup) { + return ProductGroup.query({}).$promise; +} diff --git a/brewman/static/app/product-group/product-group.component.ts b/brewman/static/app/product-group/product-group.component.ts new file mode 100644 index 00000000..9ea3eba2 --- /dev/null +++ b/brewman/static/app/product-group/product-group.component.ts @@ -0,0 +1,7 @@ +import {ProductGroupController} from "./product-group.controller"; + +export const ProductGroupComponent = { + templateUrl: '/app/product-group/product-group-detail.html', + controller: ProductGroupController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/product-group/product-group.controller.js b/brewman/static/app/product-group/product-group.controller.js deleted file mode 100644 index 65097abc..00000000 --- a/brewman/static/app/product-group/product-group.controller.js +++ /dev/null @@ -1,33 +0,0 @@ -angular - .module('overlord') - .controller('ProductGroupController', ProductGroupController); -ProductGroupController.$inject = ['$scope', '$location', 'productGroup']; -function ProductGroupController($scope, $location, productGroup) { - $scope.productGroup = productGroup; - - $scope.save = function () { - $scope.productGroup.$save(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/ProductGroups') - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.productGroup.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/ProductGroups') - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.foName = true; -} - -ProductGroupController.resolve = { - productGroup: ['$route', 'ProductGroup', function ($route, ProductGroup) { - var id = $route.current.params.id; - return ProductGroup.get({id: id}).$promise; - }] -}; diff --git a/brewman/static/app/product-group/product-group.controller.ts b/brewman/static/app/product-group/product-group.controller.ts new file mode 100644 index 00000000..17d7cf6a --- /dev/null +++ b/brewman/static/app/product-group/product-group.controller.ts @@ -0,0 +1,28 @@ +export class ProductGroupController { + static $inject = ['$scope', '$location', 'Messages']; + foName: boolean; + productGroup: any; + + constructor(public $scope, public $location, public Messages) { + this.productGroup = $scope.$parent.res.productGroup; + this.foName = true; + } + + save() { + this.productGroup.$save((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/ProductGroups') + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.productGroup.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/ProductGroups') + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } +} diff --git a/brewman/static/app/product-group/product-group.resolver.ts b/brewman/static/app/product-group/product-group.resolver.ts new file mode 100644 index 00000000..2956bcf4 --- /dev/null +++ b/brewman/static/app/product-group/product-group.resolver.ts @@ -0,0 +1,4 @@ +export function ProductGroupResolver($route, ProductGroup) { + const id = $route.current.params.id; + return ProductGroup.get({id: id}).$promise; +} diff --git a/brewman/static/app/product-group/product-group.service.ts b/brewman/static/app/product-group/product-group.service.ts new file mode 100644 index 00000000..56ccec44 --- /dev/null +++ b/brewman/static/app/product-group/product-group.service.ts @@ -0,0 +1,6 @@ +export function ProductGroup($resource) { + return $resource('/api/ProductGroup/:id', + {id: '@ProductGroupID'}, { + query: {method: 'GET', params: {list: true}, isArray: true} + }); +} diff --git a/brewman/static/app/product-ledger/product-ledger.component.ts b/brewman/static/app/product-ledger/product-ledger.component.ts new file mode 100644 index 00000000..d9b8aef6 --- /dev/null +++ b/brewman/static/app/product-ledger/product-ledger.component.ts @@ -0,0 +1,7 @@ +import {ProductLedgerController} from "./product-ledger.controller"; + +export const ProductLedgerComponent = { + templateUrl: '/app/product-ledger/product-ledger.html', + controller: ProductLedgerController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/product-ledger/product-ledger.controller.js b/brewman/static/app/product-ledger/product-ledger.controller.js deleted file mode 100644 index 9183e03d..00000000 --- a/brewman/static/app/product-ledger/product-ledger.controller.js +++ /dev/null @@ -1,61 +0,0 @@ -angular - .module('overlord') - .controller('ProductLedgerController', ProductLedgerController); -ProductLedgerController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'productLedger', 'ProductLedger', 'Product', 'uibDateParser']; -function ProductLedgerController($scope, $routeParams, $location, asDate, productLedger, ProductLedger, Product, dateParser) { - var _info_StartDate = dateParser.parse(productLedger.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(productLedger.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = productLedger; - $scope.show = function () { - var id = $scope.info.Product.ProductID; - if (id === $routeParams.id && $scope.info.StartDate === $routeParams.StartDate && $scope.info.FinishDate === $routeParams.FinishDate) { - ProductLedger.get({ - id: id, - StartDate: $scope.info.StartDate, - FinishDate: $scope.info.FinishDate - }, function (data) { - $scope.info = data; - }); - } else { - $location.path('/ProductLedger/' + $scope.info.Product.ProductID).search('StartDate', $scope.info.StartDate).search('FinishDate', $scope.info.FinishDate); - } - }; - $scope.downloadTable = function () { - var table = $('#gvGrid'), - html = table.clone().wrap('
').parent().html(); - html = html.replace(/á/g, 'á'); - window.open('data:application/vnd.ms-excel;charset=UTF-8,' + encodeURIComponent(html)); - }; - - $scope.products = function ($viewValue) { - return Product.autocomplete({term: $viewValue, count: 20}).$promise; - }; - $scope.foProduct = true; -} -ProductLedgerController.resolve = { - productLedger: ['$route', 'ProductLedger', function ($route, ProductLedger) { - var id = $route.current.params.id, - startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(id)) { - return ProductLedger.get({}).$promise; - } else { - return ProductLedger.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; diff --git a/brewman/static/app/product-ledger/product-ledger.controller.ts b/brewman/static/app/product-ledger/product-ledger.controller.ts new file mode 100644 index 00000000..08938862 --- /dev/null +++ b/brewman/static/app/product-ledger/product-ledger.controller.ts @@ -0,0 +1,61 @@ +import * as $ from 'jquery'; + +export class ProductLedgerController { + static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'ProductLedger', 'Product', 'uibDateParser']; + _info_StartDate: any; + _info_FinishDate: any; + info: any; + foProduct; + boolean; + productLedger: any; + + constructor(public $scope, public $routeParams, public $location, public asDate, public ProductLedger, public Product, public dateParser) { + this.productLedger = $scope.$parent.res.productLedger; + this._info_StartDate = dateParser.parse(this.productLedger.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.productLedger.FinishDate, "dd-MMM-yyyy"); + this.info = this.productLedger; + this.foProduct = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + const id = this.info.Product.ProductID; + if (id === this.$routeParams.id && this.info.StartDate === this.$routeParams.StartDate && this.info.FinishDate === this.$routeParams.FinishDate) { + this.ProductLedger.get({ + id: id, + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }, (data) => { + this.info = data; + }); + } else { + this.$location.path('/ProductLedger/' + this.info.Product.ProductID).search('StartDate', this.info.StartDate).search('FinishDate', this.info.FinishDate); + } + } + + downloadTable() { + let table = $('#gvGrid'), + html = table.clone().wrap('
').parent().html(); + html = html.replace(/á/g, 'á'); + window.open('data:application/vnd.ms-excel;charset=UTF-8,' + encodeURIComponent(html)); + } + + products($viewValue) { + return this.Product.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/product-ledger/product-ledger.html b/brewman/static/app/product-ledger/product-ledger.html index ded849e1..d70b4cc5 100644 --- a/brewman/static/app/product-ledger/product-ledger.html +++ b/brewman/static/app/product-ledger/product-ledger.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -30,11 +30,11 @@
- + -
@@ -56,7 +56,7 @@
- + @@ -71,22 +71,22 @@ - - - - - - - - - - + + + + + + + + + +
{{item.Type}} {{item.Name}} {{item.Debit | accounting}}
{{journal.Ledger.Name}} {{journal.Amount | currency}}
{{item.Name}}
{{item.Date}} {{item.Name}} {{item.Type}}
{{info.Footer.Date}}{{info.Footer.Name}}{{info.Footer.Type}}{{info.Footer.Narration}}{{info.Footer.DebitQ | number:2}}{{info.Footer.DebitA | currency}}{{info.Footer.CreditQ | number:2}}{{info.Footer.CreditA | currency}}{{info.Footer.RunningQ | number:2}}{{info.Footer.RunningA | currency}}{{vm.info.Footer.Date}}{{vm.info.Footer.Name}}{{vm.info.Footer.Type}}{{vm.info.Footer.Narration}}{{vm.info.Footer.DebitQ | number:2}}{{vm.info.Footer.DebitA | currency}}{{vm.info.Footer.CreditQ | number:2}}{{vm.info.Footer.CreditA | currency}}{{vm.info.Footer.RunningQ | number:2}}{{vm.info.Footer.RunningA | currency}}
-
diff --git a/brewman/static/app/product-ledger/product-ledger.resolver.ts b/brewman/static/app/product-ledger/product-ledger.resolver.ts new file mode 100644 index 00000000..3756a235 --- /dev/null +++ b/brewman/static/app/product-ledger/product-ledger.resolver.ts @@ -0,0 +1,13 @@ +import * as angular from 'angular'; + +export function ProductLedgerResolver($route, ProductLedger) { + const id = $route.current.params.id, + startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(id)) { + return ProductLedger.get({}).$promise; + } else { + return ProductLedger.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/product-ledger/product-ledger.service.ts b/brewman/static/app/product-ledger/product-ledger.service.ts new file mode 100644 index 00000000..36260593 --- /dev/null +++ b/brewman/static/app/product-ledger/product-ledger.service.ts @@ -0,0 +1,3 @@ +export function ProductLedger($resource) { + return $resource('/api/ProductLedger/:id'); +} diff --git a/brewman/static/app/product/product-detail.html b/brewman/static/app/product/product-detail.html index 8ebe73d2..62af4678 100644 --- a/brewman/static/app/product/product-detail.html +++ b/brewman/static/app/product/product-detail.html @@ -3,47 +3,47 @@
- + - +
- + - + - +
- - + + - - +
- + Is Purchased? - + Is Sold? - + Is Active? @@ -51,13 +51,13 @@
- - {{pg.Name}} + + {{pg.Name}}
- Save - Delete + Save + Delete
diff --git a/brewman/static/app/product/product-list.component.ts b/brewman/static/app/product/product-list.component.ts new file mode 100644 index 00000000..80a3bcfb --- /dev/null +++ b/brewman/static/app/product/product-list.component.ts @@ -0,0 +1,7 @@ +import {ProductListController} from "./product-list.controller"; + +export const ProductListComponent = { + templateUrl: '/app/product/product-list.html', + controller: ProductListController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/product/product-list.controller.js b/brewman/static/app/product/product-list.controller.js deleted file mode 100644 index 459cd96f..00000000 --- a/brewman/static/app/product/product-list.controller.js +++ /dev/null @@ -1,133 +0,0 @@ -angular - .module('overlord') - .controller('ProductListController', ProductListController); -ProductListController.$inject = ['$scope', '$location', '$routeParams', 'Tokenizer', 'products']; -function ProductListController($scope, $location, $routeParams, Tokenizer, products) { - $scope.search = $routeParams.q || ''; - $scope.showExtended = false; - $scope.info = products; - $scope.product_groups = _.reduce(products, function (acculumator, item) { - if (!acculumator.includes(item.ProductGroup)) { - acculumator.push(item.ProductGroup); - } - return acculumator; - }, []).sort(); - $scope.isPurchased = function (isPurchased) { - if (arguments.length === 0) { - return $scope._isPurchased; - } - $scope._isPurchased = isPurchased; - var re = /(('[p]'|"[p]"|[p]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, - matches = $scope.search.match(re), - st = isPurchased === 'null' ? '' : 'p:' + isPurchased, - search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st); - $scope.search = search.trim(); - }; - - $scope.isSold = function (isSold) { - if (arguments.length === 0) { - return $scope._isSold; - } - $scope._isSold = isSold; - var re = /(('[s]'|"[s]"|[s]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, - matches = $scope.search.match(re), - st = isSold === 'null' ? '' : 's:' + isSold, - search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st); - $scope.search = search.trim(); - }; - - $scope.productGroup = function (productGroup) { - if (arguments.length === 0) { - - return $scope._productGroup; - } - $scope._productGroup = productGroup; - var re = /(('[t]'|"[t]"|[t]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, - matches = $scope.search.match(re), - st = 't:"' + productGroup + '"', - search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st); - $scope.search = search.trim(); - }; - - $scope.$watch('search', function (value) { - $scope.filterProducts(value); - }, true); - - $scope.$on('$destroy', function () { - Tokenizer.doFilter.cache = {}; - }); - - $scope.searchInfo = { - comparator: { - 'n': {'Col': 'Name', 'Comparator': 'text'}, - 'u': {'Col': 'Units', 'Comparator': 'text'}, - 'a': {'Col': 'IsActive', 'Comparator': 'boolean'}, - 's': {'Col': 'IsSold', 'Comparator': 'boolean'}, - 'p': {'Col': 'IsPurchased', 'Comparator': 'boolean'}, - 't': {'Col': 'ProductGroup', 'Comparator': 'text'}, - 'y': {'Col': 'ProductYield', 'Comparator': 'numeric'} - }, - def: 'n', - sorter: { - 'c': 'Code', - 'n': 'Name', - 'u': 'Units', - 'p': 'Price', - 't': 'ProductGroup', - 'a': 'IsActive', - 'y': 'ProductYield', - 'f': 'Fraction', - 'fu': 'FractionUnits' - }, - flags: { - 'e': 'boolean' - } - }; - $scope.filterProducts = _.debounce(function (q) { - if (q !== $scope._search) { - $scope._search = q; - if (angular.isUndefined(q) || q === '') { - $location.path('/Products').search('q', null).replace(); - } else { - $location.path('/Products').search({'q': q}).replace(); - } - $scope.$apply(function () { - var matches = Tokenizer.parseFilterString(q, $scope.searchInfo); - $scope.showExtended = 'e' in matches.f; - $scope.products = Tokenizer.doFilter(q, $scope.info, matches); - - }); - } - }, 350); - - $scope.selected = -1; - $scope.setSelected = function (index) { - $scope.selected = Math.min(Math.max(0, index), $scope.products.length - 1); - }; - $scope.shortcuts = { - 'up': function (e) { - if ($scope.selected > 0) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected - 1), $scope.products.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - }, - 'down': function (e) { - if ($scope.selected < $scope.products.length - 1) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected + 1), $scope.products.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - } - }; -} - -ProductListController.resolve = { - products: ['Product', function (Product) { - return Product.query({}).$promise; - }] -}; diff --git a/brewman/static/app/product/product-list.controller.ts b/brewman/static/app/product/product-list.controller.ts new file mode 100644 index 00000000..63343930 --- /dev/null +++ b/brewman/static/app/product/product-list.controller.ts @@ -0,0 +1,140 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import * as $ from 'jquery'; + +export class ProductListController { + static $inject = ['$scope', '$location', '$routeParams', 'Tokenizer']; + search: any; + showExtended: boolean; + info: any; + product_groups: any; + searchInfo: any; + filterProducts: any; + selected: any; + shortcuts: any; + products: any; + + constructor(public $scope, public $location, public $routeParams, public Tokenizer) { + this.products = $scope.$parent.res.products; + this.search = $routeParams.q || ''; + this.showExtended = false; + this.product_groups = _.reduce(this.products, function (acculumator, item) { + if (!acculumator.includes(item.ProductGroup)) { + acculumator.push(item.ProductGroup); + } + return acculumator; + }, []).sort(); + $scope.$watch('vm.search', (value) => { + this.filterProducts(value); + }, true); + + $scope.$on('$destroy', function () { + Tokenizer.doFilter.cache = {}; + }); + + this.searchInfo = { + comparator: { + 'n': {'Col': 'Name', 'Comparator': 'text'}, + 'u': {'Col': 'Units', 'Comparator': 'text'}, + 'a': {'Col': 'IsActive', 'Comparator': 'boolean'}, + 's': {'Col': 'IsSold', 'Comparator': 'boolean'}, + 'p': {'Col': 'IsPurchased', 'Comparator': 'boolean'}, + 't': {'Col': 'ProductGroup', 'Comparator': 'text'}, + 'y': {'Col': 'ProductYield', 'Comparator': 'numeric'} + }, + def: 'n', + sorter: { + 'c': 'Code', + 'n': 'Name', + 'u': 'Units', + 'p': 'Price', + 't': 'ProductGroup', + 'a': 'IsActive', + 'y': 'ProductYield', + 'f': 'Fraction', + 'fu': 'FractionUnits' + }, + flags: { + 'e': 'boolean' + } + }; + this.filterProducts = _.debounce((q) => { + if (q !== $scope._search) { + $scope._search = q; + if (angular.isUndefined(q) || q === '') { + this.$location.path('/Products').search('q', null).replace(); + } else { + this.$location.path('/Products').search({'q': q}).replace(); + } + $scope.$apply(() => { + const matches = Tokenizer.parseFilterString(q, this.searchInfo); + this.showExtended = 'e' in matches.f; + this.products = Tokenizer.doFilter(q, this.info, matches); + }); + } + }, 350); + + this.selected = -1; + this.shortcuts = { + 'up': (e) => { + if (this.selected > 0) { + $scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected - 1), this.products.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + }, + 'down': (e) => { + if (this.selected < this.products.length - 1) { + $scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected + 1), this.products.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + } + }; + } + + isPurchased(isPurchased) { + if (arguments.length === 0) { + return this.$scope._isPurchased; + } + this.$scope._isPurchased = isPurchased; + const re = /(('[p]'|"[p]"|[p]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, + matches = this.search.match(re), + st = isPurchased === 'null' ? '' : 'p:' + isPurchased, + search = (matches === null) ? this.search.trim() + ' ' + st : this.search.replace(re, st); + this.search = search.trim(); + } + + isSold(isSold) { + if (arguments.length === 0) { + return this.$scope._isSold; + } + this.$scope._isSold = isSold; + const re = /(('[s]'|"[s]"|[s]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, + matches = this.search.match(re), + st = isSold === 'null' ? '' : 's:' + isSold, + search = (matches === null) ? this.search.trim() + ' ' + st : this.search.replace(re, st); + this.search = search.trim(); + } + + productGroup(productGroup) { + if (arguments.length === 0) { + + return this.$scope._productGroup; + } + this.$scope._productGroup = productGroup; + const re = /(('[t]'|"[t]"|[t]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, + matches = this.search.match(re), + st = 't:"' + productGroup + '"', + search = (matches === null) ? this.search.trim() + ' ' + st : this.search.replace(re, st); + this.search = search.trim(); + } + + setSelected(index) { + this.selected = Math.min(Math.max(0, index), this.products.length - 1); + } +} diff --git a/brewman/static/app/product/product-list.html b/brewman/static/app/product/product-list.html index e751cd38..be4d906c 100644 --- a/brewman/static/app/product/product-list.html +++ b/brewman/static/app/product/product-list.html @@ -1,7 +1,7 @@

Products

- @@ -12,7 +12,7 @@
- + All Yes No @@ -20,7 +20,7 @@ - + All Yes No @@ -28,12 +28,12 @@ - - {{pg}} + + {{pg}}
- +
@@ -45,10 +45,10 @@ - + - diff --git a/brewman/static/app/product/product-list.resolver.ts b/brewman/static/app/product/product-list.resolver.ts new file mode 100644 index 00000000..531780a4 --- /dev/null +++ b/brewman/static/app/product/product-list.resolver.ts @@ -0,0 +1,3 @@ +export function ProductListResolver(Product) { + return Product.query({}).$promise; +} diff --git a/brewman/static/app/product/product.component.ts b/brewman/static/app/product/product.component.ts new file mode 100644 index 00000000..17eeb836 --- /dev/null +++ b/brewman/static/app/product/product.component.ts @@ -0,0 +1,7 @@ +import {ProductController} from "./product.controller"; + +export const ProductComponent = { + templateUrl: '/app/product/product-detail.html', + controller: ProductController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/product/product.controller.js b/brewman/static/app/product/product.controller.js deleted file mode 100644 index 5cdd2392..00000000 --- a/brewman/static/app/product/product.controller.js +++ /dev/null @@ -1,61 +0,0 @@ -angular - .module('overlord') - .controller('ProductController', ProductController); -ProductController.$inject = ['$scope', '$location', '$window', '$mdDialog', 'product', 'productGroups']; -function ProductController($scope, $location, $window, $mdDialog, product, productGroups) { - $scope.product = product; - $scope.productGroups = productGroups; - - $scope.save = function () { - $scope.product.$save(function (u) { - $scope.toasts.push({Type: 'Success', Message: u.Code}); - $window.history.back(); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.product.$delete(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $window.history.back(); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.confirm = function (ev) { - $mdDialog.show({ - templateUrl: '/template/modal/confirm-material.html', - parent: angular.element(document.body), - targetEvent: ev, - clickOutsideToClose: false, - fullscreen: true, - controller: ['$scope', '$mdDialog', function ($scope, $mdDialog) { - $scope.title = "Delete Product"; - $scope.body = "Are you sure that you want to delete this product? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $mdDialog.hide(); - }; - $scope.cancel = function () { - $mdDialog.cancel(); - }; - }] - }).then(function () { - $scope.delete(); - }); - }; - $scope.foName = true; -} - -ProductController.resolve = { - product: ['$route', 'Product', function ($route, Product) { - var id = $route.current.params.id; - - return Product.get({id: id}).$promise; - }], - productGroups: ['ProductGroup', function (ProductGroup) { - return ProductGroup.query({}).$promise; - }] -}; diff --git a/brewman/static/app/product/product.controller.ts b/brewman/static/app/product/product.controller.ts new file mode 100644 index 00000000..5139ba47 --- /dev/null +++ b/brewman/static/app/product/product.controller.ts @@ -0,0 +1,53 @@ +import * as angular from 'angular'; + +export class ProductController { + static $inject = ['$scope', '$location', '$window', '$mdDialog', 'productGroups', 'Messages']; + foName: boolean; + product: any; + + constructor(public $scope, public $location, public $window, public $mdDialog, public productGroups, public Messages) { + this.product = $scope.$parent.res.product; + this.foName = true; + } + + save() { + this.product.$save((u) => { + this.Messages.push({Type: 'Success', Message: u.Code}); + this.$window.history.back(); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.product.$delete(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$window.history.back(); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + confirm(ev) { + this.$mdDialog.show({ + templateUrl: '/template/modal/confirm-material.html', + parent: angular.element(document.body), + targetEvent: ev, + clickOutsideToClose: false, + fullscreen: true, + controller: ['$scope', '$mdDialog', function ($scope, $mdDialog) { + this.title = "Delete Product"; + this.body = "Are you sure that you want to delete this product? This cannot be undone."; + this.isDelete = true; + let ok = () => { + $mdDialog.hide(); + }; + let cancel = () => { + $mdDialog.cancel(); + } + }] + }).then(() => { + this.delete(); + }); + } +} diff --git a/brewman/static/app/product/product.resolver.ts b/brewman/static/app/product/product.resolver.ts new file mode 100644 index 00000000..02ab68cd --- /dev/null +++ b/brewman/static/app/product/product.resolver.ts @@ -0,0 +1,4 @@ +export function ProductResolver($route, Product) { + const id = $route.current.params.id; + return Product.get({id: id}).$promise; +} diff --git a/brewman/static/app/product/product.service.ts b/brewman/static/app/product/product.service.ts new file mode 100644 index 00000000..1621758f --- /dev/null +++ b/brewman/static/app/product/product.service.ts @@ -0,0 +1,7 @@ +export function Product($resource) { + return $resource('/api/Product/:id', + {id: '@ProductID'}, { + query: {method: 'GET', params: {list: true}, isArray: true}, + autocomplete: {method: 'GET', params: {term: ''}, isArray: true} + }); +} diff --git a/brewman/static/app/profit-loss/profit-loss.component.ts b/brewman/static/app/profit-loss/profit-loss.component.ts new file mode 100644 index 00000000..658083e7 --- /dev/null +++ b/brewman/static/app/profit-loss/profit-loss.component.ts @@ -0,0 +1,7 @@ +import {ProfitLossController} from "./profit-loss.controller"; + +export const ProfitLossComponent = { + templateUrl: '/app/profit-loss/profit-loss.html', + controller: ProfitLossController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/profit-loss/profit-loss.controller.js b/brewman/static/app/profit-loss/profit-loss.controller.js deleted file mode 100644 index bf2092e1..00000000 --- a/brewman/static/app/profit-loss/profit-loss.controller.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -var ProfitLossController = ['$scope', '$location', 'asDateFilter', 'profit_loss', 'uibDateParser', function ($scope, $location, asDate, profit_loss, dateParser) { - var _info_StartDate = dateParser.parse(profit_loss.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(profit_loss.FinishDate, "dd-MMM-yyyy");; - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = profit_loss; - $scope.show = function () { - $location.path('/ProfitLoss').search({StartDate: $scope.info.StartDate, FinishDate: $scope.info.FinishDate}); - }; - $scope.foDate = true; -}]; - -ProfitLossController.resolve = { - profit_loss: ['$route', 'ProfitLoss', function ($route, ProfitLoss) { - var startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return ProfitLoss.get({}).$promise; - } else { - return ProfitLoss.get({StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; \ No newline at end of file diff --git a/brewman/static/app/profit-loss/profit-loss.controller.ts b/brewman/static/app/profit-loss/profit-loss.controller.ts new file mode 100644 index 00000000..facfbdc3 --- /dev/null +++ b/brewman/static/app/profit-loss/profit-loss.controller.ts @@ -0,0 +1,36 @@ +export class ProfitLossController { + static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + info: any; + _info_StartDate: any; + _info_FinishDate: any; + foDate: boolean; + profit_loss: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.profit_loss = $scope.$parent.res.profit_loss; + this._info_StartDate = dateParser.parse(this.profit_loss.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.profit_loss.FinishDate, "dd-MMM-yyyy"); + this.info = this.profit_loss; + this.foDate = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/ProfitLoss').search({StartDate: this.info.StartDate, FinishDate: this.info.FinishDate}); + } +} diff --git a/brewman/static/app/profit-loss/profit-loss.html b/brewman/static/app/profit-loss/profit-loss.html index cc50621f..04cefc07 100644 --- a/brewman/static/app/profit-loss/profit-loss.html +++ b/brewman/static/app/profit-loss/profit-loss.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
@@ -39,7 +39,7 @@
- + @@ -47,7 +47,7 @@ - + diff --git a/brewman/static/app/profit-loss/profit-loss.resolver.ts b/brewman/static/app/profit-loss/profit-loss.resolver.ts new file mode 100644 index 00000000..a5611ab7 --- /dev/null +++ b/brewman/static/app/profit-loss/profit-loss.resolver.ts @@ -0,0 +1,12 @@ +import * as angular from 'angular'; + +export function ProfitLossResolver($route, ProfitLoss) { + const startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return ProfitLoss.get({}).$promise; + } else { + return ProfitLoss.get({StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/profit-loss/profit-loss.service.ts b/brewman/static/app/profit-loss/profit-loss.service.ts new file mode 100644 index 00000000..0801c9bb --- /dev/null +++ b/brewman/static/app/profit-loss/profit-loss.service.ts @@ -0,0 +1,3 @@ +export function ProfitLoss($resource) { + return $resource('/api/ProfitLoss'); +} diff --git a/brewman/static/app/purchase-entries/purchase-entries.component.ts b/brewman/static/app/purchase-entries/purchase-entries.component.ts new file mode 100644 index 00000000..e7064875 --- /dev/null +++ b/brewman/static/app/purchase-entries/purchase-entries.component.ts @@ -0,0 +1,7 @@ +import {PurchaseEntriesController} from "./purchase-entries.controller"; + +export const PurchaseEntriesComponent = { + templateUrl: '/app/purchase-entries/purchase-entries.html', + controller: PurchaseEntriesController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/purchase-entries/purchase-entries.controller.js b/brewman/static/app/purchase-entries/purchase-entries.controller.js deleted file mode 100644 index 85da136a..00000000 --- a/brewman/static/app/purchase-entries/purchase-entries.controller.js +++ /dev/null @@ -1,44 +0,0 @@ -angular - .module('overlord') - .controller('PurchaseEntriesController', PurchaseEntriesController); -PurchaseEntriesController.$inject = ['$scope', '$location', 'asDateFilter', 'purchaseEntries', 'uibDateParser']; -function PurchaseEntriesController($scope, $location, asDate, purchaseEntries, dateParser) { - var _info_StartDate = dateParser.parse(purchaseEntries.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(purchaseEntries.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = purchaseEntries; - - $scope.show = function () { - $location.path('/PurchaseEntries').search({ - StartDate: $scope.info.StartDate, - FinishDate: $scope.info.FinishDate - }); - }; - $scope.foDate = true; -} - -PurchaseEntriesController.resolve = { - purchaseEntries: ['$route', 'PurchaseEntries', function ($route, PurchaseEntries) { - var startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return PurchaseEntries.get({}).$promise; - } else { - return PurchaseEntries.get({StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; diff --git a/brewman/static/app/purchase-entries/purchase-entries.controller.ts b/brewman/static/app/purchase-entries/purchase-entries.controller.ts new file mode 100644 index 00000000..d56a8302 --- /dev/null +++ b/brewman/static/app/purchase-entries/purchase-entries.controller.ts @@ -0,0 +1,39 @@ +export class PurchaseEntriesController { + static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + info: any; + _info_StartDate: any; + _info_FinishDate: any; + foDate: boolean; + purchaseEntries: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.purchaseEntries = $scope.$parent.res.purchaseEntries; + this._info_StartDate = dateParser.parse(this.purchaseEntries.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.purchaseEntries.FinishDate, "dd-MMM-yyyy"); + this.info = this.purchaseEntries; + this.foDate = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/PurchaseEntries').search({ + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }); + } +} diff --git a/brewman/static/app/purchase-entries/purchase-entries.html b/brewman/static/app/purchase-entries/purchase-entries.html index 7a6b7eec..685a7e9c 100644 --- a/brewman/static/app/purchase-entries/purchase-entries.html +++ b/brewman/static/app/purchase-entries/purchase-entries.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
Code
{{item.Code}}{{item.Name}} ({{showExtended ? item.Fraction + ' ' + item.FractionUnits + ' = 1 ' : + {{item.Name}} ({{vm.showExtended ? item.Fraction + ' ' + item.FractionUnits + ' = 1 ' : ''}}{{item.Units}}) {{item.CostPrice | currency}} {{item.ProductYield * 100 | number:2}}%
{{item.Group}} {{item.Name}} {{item.SubAmount | currency | clr}}
{{item.Group}} {{item.Name}} {{item.SubAmount | currency | clr}}
@@ -40,7 +40,7 @@ - + diff --git a/brewman/static/app/purchase-entries/purchase-entries.resolver.ts b/brewman/static/app/purchase-entries/purchase-entries.resolver.ts new file mode 100644 index 00000000..baaf484d --- /dev/null +++ b/brewman/static/app/purchase-entries/purchase-entries.resolver.ts @@ -0,0 +1,12 @@ +import * as angular from 'angular'; + +export function PurchaseEntriesResolver($route, PurchaseEntries) { + const startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return PurchaseEntries.get({}).$promise; + } else { + return PurchaseEntries.get({StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/purchase-entries/purchase-entries.service.ts b/brewman/static/app/purchase-entries/purchase-entries.service.ts new file mode 100644 index 00000000..a337e4cc --- /dev/null +++ b/brewman/static/app/purchase-entries/purchase-entries.service.ts @@ -0,0 +1,3 @@ +export function PurchaseEntries($resource) { + return $resource('/api/PurchaseEntries'); +} diff --git a/brewman/static/app/purchase-return/purchase-return-modal.controller.js b/brewman/static/app/purchase-return/purchase-return-modal.controller.js deleted file mode 100644 index fdb6bea0..00000000 --- a/brewman/static/app/purchase-return/purchase-return-modal.controller.js +++ /dev/null @@ -1,22 +0,0 @@ -angular - .module('overlord') - .controller('PurchaseReturnModalController', PurchaseReturnModalController); -PurchaseReturnModalController.$inject = ['$scope', '$uibModalInstance', 'edit', 'Batch']; -function PurchaseReturnModalController($scope, $modalInstance, edit, Batch) { - $scope.edit = edit; - $scope.ok = function () { - $scope.edit.Product = $scope.edit.Batch.Product; - $scope.edit.Quantity = Number($scope.edit.Quantity); - $scope.edit.Tax = $scope.edit.Batch.Tax; - $scope.edit.Discount = $scope.edit.Batch.Discount; - $scope.edit.Rate = $scope.edit.Batch.Rate; - $scope.edit.Amount = $scope.edit.Quantity * $scope.edit.Rate * (1 + $scope.edit.Tax) * (1 - $scope.edit.Discount); - $modalInstance.close($scope.edit); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - $scope.batches = function ($viewValue) { - return Batch.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} \ No newline at end of file diff --git a/brewman/static/app/purchase-return/purchase-return-modal.controller.ts b/brewman/static/app/purchase-return/purchase-return-modal.controller.ts new file mode 100644 index 00000000..b5c60981 --- /dev/null +++ b/brewman/static/app/purchase-return/purchase-return-modal.controller.ts @@ -0,0 +1,26 @@ +export class PurchaseReturnModalController { + static $inject = ['$scope', '$uibModalInstance', 'Batch']; + edit:any; + + constructor(public $scope, public $modalInstance, public Batch) { + this.edit = $scope.$resolve.edit; + } + + ok() { + this.edit.Product = this.edit.Batch.Product; + this.edit.Quantity = Number(this.edit.Quantity); + this.edit.Tax = this.edit.Batch.Tax; + this.edit.Discount = this.edit.Batch.Discount; + this.edit.Rate = this.edit.Batch.Rate; + this.edit.Amount = this.edit.Quantity * this.edit.Rate * (1 + this.edit.Tax) * (1 - this.edit.Discount); + this.$modalInstance.close(this.edit); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + + batches($viewValue) { + return this.Batch.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/purchase-return/purchase-return-modal.html b/brewman/static/app/purchase-return/purchase-return-modal.html index 73211489..9238d90f 100644 --- a/brewman/static/app/purchase-return/purchase-return-modal.html +++ b/brewman/static/app/purchase-return/purchase-return-modal.html @@ -8,17 +8,17 @@
-
- +
diff --git a/brewman/static/app/purchase-return/purchase-return-voucher.resolver.ts b/brewman/static/app/purchase-return/purchase-return-voucher.resolver.ts new file mode 100644 index 00000000..1cdf5376 --- /dev/null +++ b/brewman/static/app/purchase-return/purchase-return-voucher.resolver.ts @@ -0,0 +1,10 @@ +import * as angular from 'angular'; + +export function PurchaseReturnVoucherResolver($route, Voucher) { + const id = $route.current.params.id; + if (angular.isUndefined(id)) { + return Voucher.get({type: 'Purchase Return'}).$promise; + } else { + return Voucher.get({id: id}).$promise; + } +} diff --git a/brewman/static/app/purchase-return/purchase-return.component.ts b/brewman/static/app/purchase-return/purchase-return.component.ts new file mode 100644 index 00000000..5ea91b0f --- /dev/null +++ b/brewman/static/app/purchase-return/purchase-return.component.ts @@ -0,0 +1,7 @@ +import {PurchaseReturnController} from "./purchase-return.controller"; + +export const PurchaseReturnComponent = { + templateUrl: '/app/purchase-return/purchase-return.html', + controller: PurchaseReturnController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/purchase-return/purchase-return.controller.js b/brewman/static/app/purchase-return/purchase-return.controller.js deleted file mode 100644 index bb19c9a4..00000000 --- a/brewman/static/app/purchase-return/purchase-return.controller.js +++ /dev/null @@ -1,202 +0,0 @@ -angular - .module('overlord') - .controller('PurchaseReturnController', PurchaseReturnController); -PurchaseReturnController.$inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'uploadedImageResizer', 'voucher', 'Account', 'Batch', 'uibDateParser']; -function PurchaseReturnController($scope, $location, asDate, $modal, uploadedImageResizer, voucher, Account, Batch, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.voucher = voucher; - $scope.rate = 0; - function getOld(productID, inventories) { - return _.find(inventories, function (inventory) { - return inventory.Product.ProductID === productID; - }); - } - - $scope.$on("fileSelected", function (event, args) { - uploadedImageResizer(args, $scope.voucher.Files); - }); - - - $scope.deleteFile = function (item) { - var index = $scope.voucher.Files.indexOf(item); - $scope.voucher.Files.splice(index, 1); - }; - - $scope.zoomImage = function (item) { - $modal.open({ - templateUrl: '/template/modal/image.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.imageUrl = item.Resized; - $scope.size = null; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - }; - - $scope.add = function () { - var oldInventory = getOld($scope.batch.Product.ProductID, $scope.voucher.Inventories), - quantity = Number($scope.quantity); - - if (!$scope.batch || !$scope.batch.Product.ProductID || !quantity) { - return; - } - - if (angular.isUndefined(oldInventory) && quantity <= $scope.batch.QuantityRemaining) { - $scope.voucher.Inventories.push( - { - Product: $scope.batch.Product, - Quantity: quantity, - Rate: $scope.batch.Rate, - Tax: $scope.batch.Tax, - Discount: $scope.batch.Discount, - Amount: quantity * $scope.batch.Rate * (1 + $scope.batch.Tax) * (1 - $scope.batch.Discount), - Batch: $scope.batch - }); - delete $scope.batch; - delete $scope.quantity; - $scope.foBatch = true; - } - }; - $scope.removeInventory = function (inventory) { - var index = $scope.voucher.Inventories.indexOf(inventory); - $scope.voucher.Inventories.splice(index, 1); - }; - - $scope.$watch('voucher.Inventories', function (inventories) { - var amount = 0, - i, - l; - if (!angular.isUndefined(inventories)) { - for (i = 0, l = inventories.length; i < l; i++) { - amount += Number(inventories[i].Amount); - } - } - if (!angular.isUndefined($scope.voucher.Journals)) { - for (i = 0, l = $scope.voucher.Journals.length; i < l; i++) { - if ($scope.voucher.Journals[i].Debit === 1) { - $scope.voucher.Journals[i].Amount = amount; - break; - } - } - } - }, true); - - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined($scope.perms)) { - return false; - } else if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Purchase Return']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID !== $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.save = function () { - return $scope.voucher.$save({type: 'Purchase Return'}, function (u) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Return/' + u.VoucherID); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.voucher.$delete(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Return').replace(); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.post = function () { - return $scope.voucher.$post(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.modal = function (inventory) { - $scope.selectedInventory = inventory; - var edit = {}; - angular.copy($scope.selectedInventory, edit); - var modalInstance = $modal.open({ - backdrop: true, - size: 'lg', - templateUrl: '/app/purchase-return/purchase-return-modal.html', - controller: PurchaseReturnModalController, - resolve: { - edit: function () { - return edit; - } - } - }); - modalInstance.result.then(function (updated) { - if (updated.Product.ProductID !== $scope.selectedInventory.Batch.Product.ProductID) { - var oldInventory = getOld(updated.Batch.Product.ProductID, $scope.voucher.Inventories); - if (!angular.isUndefined(oldInventory)) { - delete $scope.selectedInventory; - return false; - } - } - angular.copy(updated, $scope.selectedInventory); - delete $scope.selectedInventory; - }, function () { - delete $scope.selectedInventory; - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20, a: true}).$promise; - }; - $scope.batches = function ($viewValue) { - var params = {term: $viewValue, count: 20, date: $scope.voucher.Date}; - return Batch.autocomplete(params).$promise; - }; -} - -PurchaseReturnController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id; - if (angular.isUndefined(id)) { - return Voucher.get({type: 'Purchase Return'}).$promise; - } else { - return Voucher.get({id: id}).$promise; - } - }] -}; diff --git a/brewman/static/app/purchase-return/purchase-return.controller.ts b/brewman/static/app/purchase-return/purchase-return.controller.ts new file mode 100644 index 00000000..5026f661 --- /dev/null +++ b/brewman/static/app/purchase-return/purchase-return.controller.ts @@ -0,0 +1,220 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import {PurchaseReturnModalController} from './purchase-return-modal.controller'; + +export class PurchaseReturnController { + static $inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'UploadedImageResizer', 'Account', 'Batch', 'uibDateParser', 'Messages', 'Credentials']; + selectedInventory: any; + foBatch: boolean; + quantity: any; + batch: any; + _voucher_Date: any; + rate: any; + voucher: any; + + constructor(public $scope, public $location, public asDate, public $modal, public UploadedImageResizer, public Account, public Batch, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + this.rate = 0; + + $scope.$on("fileSelected", (event, args) => { + UploadedImageResizer(args, this.voucher.Files); + }); + + $scope.$watch('vm.voucher.Inventories', (inventories) => { + let amount = 0, + i, + l; + if (!angular.isUndefined(inventories)) { + for (i = 0, l = inventories.length; i < l; i++) { + amount += Number(inventories[i].Amount); + } + } + if (!angular.isUndefined(this.voucher.Journals)) { + for (i = 0, l = this.voucher.Journals.length; i < l; i++) { + if (this.voucher.Journals[i].Debit === 1) { + this.voucher.Journals[i].Amount = amount; + break; + } + } + } + }, true); + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + getOld(productID, inventories) { + return _.find(inventories, function (inventory) { + return inventory.Product.ProductID === productID; + }); + } + + deleteFile(item) { + const index = this.voucher.Files.indexOf(item); + this.voucher.Files.splice(index, 1); + } + + zoomImage(item) { + this.$modal.open({ + templateUrl: '/template/modal/image.html', + controller: ['$uibModalInstance', class { + imageUrl: any; + size: any; + + constructor(public $modalInstance) { + this.imageUrl = item.Resized; + this.size = null; + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + } + + add() { + let oldInventory = this.getOld(this.batch.Product.ProductID, this.voucher.Inventories), + quantity = Number(this.quantity); + + if (!this.batch || !this.batch.Product.ProductID || !quantity) { + return; + } + + if (angular.isUndefined(oldInventory) && quantity <= this.batch.QuantityRemaining) { + this.voucher.Inventories.push( + { + Product: this.batch.Product, + Quantity: quantity, + Rate: this.batch.Rate, + Tax: this.batch.Tax, + Discount: this.batch.Discount, + Amount: quantity * this.batch.Rate * (1 + this.batch.Tax) * (1 - this.batch.Discount), + Batch: this.batch + }); + delete this.batch; + delete this.quantity; + this.foBatch = true; + } + } + + removeInventory(inventory) { + const index = this.voucher.Inventories.indexOf(inventory); + this.voucher.Inventories.splice(index, 1); + } + + preventAlteration(voucher) { + if (angular.isUndefined(this.Credentials.Perms)) { + return false; + } else if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Purchase Return']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID !== this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + save() { + return this.voucher.$save({type: 'Purchase Return'}, (u) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Return/' + u.VoucherID); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.voucher.$delete(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Return').replace(); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + post() { + return this.voucher.$post(() => { + this.Messages.push({Type: 'Success', Message: ''}); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + modal(inventory) { + this.selectedInventory = inventory; + let edit = {}; + angular.copy(this.selectedInventory, edit); + const modalInstance = this.$modal.open({ + backdrop: true, + size: 'lg', + templateUrl: '/app/purchase-return/purchase-return-modal.html', + controllerAs: 'vmModal', + controller: PurchaseReturnModalController, + resolve: { + edit: function () { + return edit; + } + } + }); + modalInstance.result.then((updated) => { + if (updated.Product.ProductID !== this.selectedInventory.Batch.Product.ProductID) { + const oldInventory = this.getOld(updated.Batch.Product.ProductID, this.voucher.Inventories); + if (!angular.isUndefined(oldInventory)) { + delete this.selectedInventory; + return false; + } + } + angular.copy(updated, this.selectedInventory); + delete this.selectedInventory; + }, () => { + delete this.selectedInventory; + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20, a: true}).$promise; + } + + batches($viewValue) { + const params = {term: $viewValue, count: 20, date: this.voucher.Date}; + return this.Batch.autocomplete(params).$promise; + } +} diff --git a/brewman/static/app/purchase-return/purchase-return.html b/brewman/static/app/purchase-return/purchase-return.html index b0c1ba23..264a4c11 100644 --- a/brewman/static/app/purchase-return/purchase-return.html +++ b/brewman/static/app/purchase-return/purchase-return.html @@ -7,17 +7,17 @@
-
+
Batch
- +
- + -
@@ -56,7 +56,7 @@
- + @@ -65,12 +65,12 @@ @@ -83,14 +83,14 @@
- +
-
- - +
+ +
- - -
- Created on {{voucher.CreationDate | localTime}} and Last Edited on {{voucher.LastEditDate | localTime}} by - {{voucher.User.Name}}. Posted by {{voucher.Poster}} + Created on {{vm.voucher.CreationDate | localTime}} and Last Edited on {{vm.voucher.LastEditDate | localTime}} by + {{vm.voucher.User.Name}}. Posted by {{vm.voucher.Poster}}
\ No newline at end of file diff --git a/brewman/static/app/purchase/purchase-modal.controller.js b/brewman/static/app/purchase/purchase-modal.controller.js deleted file mode 100644 index 86ad7e14..00000000 --- a/brewman/static/app/purchase/purchase-modal.controller.js +++ /dev/null @@ -1,21 +0,0 @@ -angular - .module('overlord') - .controller('PurchaseModalController', PurchaseModalController); -PurchaseModalController.$inject = ['$scope', '$uibModalInstance', 'edit', 'Product']; -function PurchaseModalController($scope, $modalInstance, edit, Product) { - $scope.edit = edit; - $scope.ok = function () { - $scope.edit.Quantity = Number(edit.Quantity); - $scope.edit.Tax = ($scope.edit.Tax) ? Number($scope.edit.Tax) : 0; - $scope.edit.Discount = ($scope.edit.Discount) ? Number($scope.edit.Discount) : 0; - $scope.edit.Rate = Number($scope.edit.Rate); - $scope.edit.Amount = $scope.edit.Quantity * $scope.edit.Rate * (1 + $scope.edit.Tax) * (1 - $scope.edit.Discount); - $modalInstance.close($scope.edit); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - $scope.products = function ($viewValue) { - return Product.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} diff --git a/brewman/static/app/purchase/purchase-modal.controller.ts b/brewman/static/app/purchase/purchase-modal.controller.ts new file mode 100644 index 00000000..8ddaa9ef --- /dev/null +++ b/brewman/static/app/purchase/purchase-modal.controller.ts @@ -0,0 +1,25 @@ +export class PurchaseModalController { + static $inject = ['$scope', '$uibModalInstance', 'Product']; + edit: any; + + constructor(public $scope, public $modalInstance, public Product) { + this.edit = $scope.$resolve.edit; + } + + ok() { + this.edit.Quantity = Number(this.edit.Quantity); + this.edit.Tax = (this.edit.Tax) ? Number(this.edit.Tax) : 0; + this.edit.Discount = (this.edit.Discount) ? Number(this.edit.Discount) : 0; + this.edit.Rate = Number(this.edit.Rate); + this.edit.Amount = this.edit.Quantity * this.edit.Rate * (1 + this.edit.Tax) * (1 - this.edit.Discount); + this.$modalInstance.close(this.edit); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + + products($viewValue) { + return this.Product.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/purchase/purchase-modal.html b/brewman/static/app/purchase/purchase-modal.html index 27d9b47f..34689dc7 100644 --- a/brewman/static/app/purchase/purchase-modal.html +++ b/brewman/static/app/purchase/purchase-modal.html @@ -8,26 +8,26 @@
-
- +
- +
- +
- +
\ No newline at end of file diff --git a/brewman/static/app/purchase/purchase-voucher.resolver.ts b/brewman/static/app/purchase/purchase-voucher.resolver.ts new file mode 100644 index 00000000..b91bd4ac --- /dev/null +++ b/brewman/static/app/purchase/purchase-voucher.resolver.ts @@ -0,0 +1,11 @@ +import * as angular from 'angular'; + +export function PurchaseVoucherResolver($route, Voucher) { + const id = $route.current.params.id; + + if (angular.isUndefined(id)) { + return Voucher.get({type: 'Purchase'}).$promise; + } else { + return Voucher.get({id: id}).$promise; + } +} diff --git a/brewman/static/app/purchase/purchase.component.ts b/brewman/static/app/purchase/purchase.component.ts new file mode 100644 index 00000000..b6ce41d1 --- /dev/null +++ b/brewman/static/app/purchase/purchase.component.ts @@ -0,0 +1,7 @@ +import {PurchaseController} from "./purchase.controller"; + +export const PurchaseComponent = { + templateUrl: '/app/purchase/purchase.html', + controller: PurchaseController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/purchase/purchase.controller.js b/brewman/static/app/purchase/purchase.controller.js deleted file mode 100644 index 9da8edd7..00000000 --- a/brewman/static/app/purchase/purchase.controller.js +++ /dev/null @@ -1,205 +0,0 @@ -angular - .module('overlord') - .controller('PurchaseController', PurchaseController); -PurchaseController.$inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'uploadedImageResizer', 'voucher', 'Account', 'Product', 'uibDateParser']; -function PurchaseController($scope, $location, asDate, $modal, uploadedImageResizer, voucher, Account, Product, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.voucher = voucher; - function getOld(productID, inventories) { - return _.find(inventories, function (inventory) { - return inventory.Product.ProductID === productID; - }); - } - - $scope.$on("fileSelected", function (event, args) { - uploadedImageResizer(args, $scope.voucher.Files); - }); - - - $scope.deleteFile = function (item) { - var index = $scope.voucher.Files.indexOf(item); - $scope.voucher.Files.splice(index, 1); - }; - - $scope.zoomImage = function (item) { - $modal.open({ - templateUrl: '/template/modal/image.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.imageUrl = item.Resized; - $scope.size = null; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - }; - - $scope.add = function () { - var oldInventory = getOld($scope.product.ProductID, $scope.voucher.Inventories), - quantity = Number($scope.quantity), - tax = ($scope.tax) ? Number($scope.tax) : 0, - discount = ($scope.discount) ? Number($scope.discount) : 0, - price = Number($scope.product.Price); - - if (!$scope.product || !$scope.product.ProductID || !quantity || !price) { - return; - } - - if (angular.isUndefined(oldInventory)) { - $scope.voucher.Inventories.push( - { - Product: $scope.product, - Quantity: quantity, - Rate: price, - Tax: tax, - Discount: discount, - Amount: quantity * price * (1 + tax) * (1 - discount) - }); - delete $scope.product; - delete $scope.quantity; - delete $scope.tax; - delete $scope.discount; - $scope.foProduct = true; - } - }; - $scope.removeInventory = function (inventory) { - var index = $scope.voucher.Inventories.indexOf(inventory); - $scope.voucher.Inventories.splice(index, 1); - }; - - $scope.$watch('voucher.Inventories', function (inventories, oldValue) { - var amount = 0, - i, l; - if (!angular.isUndefined(inventories)) { - for (i = 0, l = inventories.length; i < l; i++) { - amount += Number(inventories[i].Amount); - } - } - if (!angular.isUndefined($scope.voucher.Journals)) { - for (i = 0, l = $scope.voucher.Journals.length; i < l; i++) { - if ($scope.voucher.Journals[i].Debit === -1) { - $scope.voucher.Journals[i].Amount = amount; - break; - } - } - } - }, true); - - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined($scope.perms)) { - return false; - } else if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Purchase']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID != $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.save = function () { - return $scope.voucher.$save({type: 'Purchase'}, function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Purchase/' + u.VoucherID); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.voucher.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Purchase').replace(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.post = function () { - return $scope.voucher.$post(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.modal = function (inventory) { - $scope.selectedInventory = inventory; - var edit = {}; - angular.copy($scope.selectedInventory, edit); - var modalInstance = $modal.open({ - backdrop: true, - size: 'lg', - templateUrl: '/app/purchase/purchase-modal.html', - controller: PurchaseModalController, - resolve: { - edit: function () { - return edit; - } - } - }); - modalInstance.result.then(function (updated) { - if (updated.Product.ProductID !== $scope.selectedInventory.Product.ProductID) { - var oldInventory = getOld(updated.Product.ProductID, $scope.voucher.Inventories); - if (!angular.isUndefined(oldInventory)) { - delete $scope.selectedInventory; - return false; - } - } - angular.copy(updated, $scope.selectedInventory); - delete $scope.selectedInventory; - }, function () { - delete $scope.selectedInventory; - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20, a: true}).$promise; - }; - - $scope.products = function ($viewValue) { - return Product.autocomplete({term: $viewValue, count: 20, a: true}).$promise; - }; -} - -PurchaseController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id; - - if (angular.isUndefined(id)) { - return Voucher.get({type: 'Purchase'}).$promise; - } else { - return Voucher.get({id: id}).$promise; - } - }] -}; diff --git a/brewman/static/app/purchase/purchase.controller.ts b/brewman/static/app/purchase/purchase.controller.ts new file mode 100644 index 00000000..06964b2f --- /dev/null +++ b/brewman/static/app/purchase/purchase.controller.ts @@ -0,0 +1,222 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import {PurchaseModalController} from './purchase-modal.controller'; + +export class PurchaseController { + static $inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'UploadedImageResizer', 'Account', 'Product', 'uibDateParser', 'Messages', 'Credentials']; + _voucher_Date: any; + selectedInventory: any; + foProduct: boolean; + product: any; + quantity: any; + tax: any; + discount: any; + voucher: any; + + constructor(public $scope, public $location, public asDate, public $modal, public UploadedImageResizer, public Account, public Product, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + + $scope.$on("fileSelected", (event, args) => { + UploadedImageResizer(args, this.voucher.Files); + }); + + $scope.$watch('vm.voucher.Inventories', (inventories, oldValue) => { + let amount = 0, + i, l; + if (!angular.isUndefined(inventories)) { + for (i = 0, l = inventories.length; i < l; i++) { + amount += Number(inventories[i].Amount); + } + } + if (!angular.isUndefined(this.voucher.Journals)) { + for (i = 0, l = this.voucher.Journals.length; i < l; i++) { + if (this.voucher.Journals[i].Debit === -1) { + this.voucher.Journals[i].Amount = amount; + break; + } + } + } + }, true); + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + getOld(productID, inventories) { + return _.find(inventories, function (inventory) { + return inventory.Product.ProductID === productID; + }); + } + + deleteFile(item) { + const index = this.voucher.Files.indexOf(item); + this.voucher.Files.splice(index, 1); + } + + zoomImage(item) { + this.$modal.open({ + templateUrl: '/template/modal/image.html', + controller: ['$uibModalInstance', class { + imageUrl: any; + size: any; + + constructor(public $modalInstance) { + this.imageUrl = item.Resized; + this.size = null; + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + } + + add() { + const oldInventory = this.getOld(this.product.ProductID, this.voucher.Inventories), + quantity = Number(this.quantity), + tax = (this.tax) ? Number(this.tax) : 0, + discount = (this.discount) ? Number(this.discount) : 0, + price = Number(this.product.Price); + + if (!this.product || !this.product.ProductID || !quantity || !price) { + return; + } + + if (angular.isUndefined(oldInventory)) { + this.voucher.Inventories.push( + { + Product: this.product, + Quantity: quantity, + Rate: price, + Tax: tax, + Discount: discount, + Amount: quantity * price * (1 + tax) * (1 - discount) + }); + delete this.product; + delete this.quantity; + delete this.tax; + delete this.discount; + this.foProduct = true; + } + } + + removeInventory(inventory) { + const index = this.voucher.Inventories.indexOf(inventory); + this.voucher.Inventories.splice(index, 1); + } + + preventAlteration(voucher) { + if (angular.isUndefined(this.Credentials.Perms)) { + return false; + } else if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Purchase']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID != this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + save() { + return this.voucher.$save({type: 'Purchase'}, (u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Purchase/' + u.VoucherID); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.voucher.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Purchase').replace(); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + post() { + return this.voucher.$post((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + modal(inventory) { + this.selectedInventory = inventory; + let edit = {}; + angular.copy(this.selectedInventory, edit); + const modalInstance = this.$modal.open({ + backdrop: true, + size: 'lg', + templateUrl: '/app/purchase/purchase-modal.html', + controllerAs: 'vmModal', + controller: PurchaseModalController, + resolve: { + edit: function () { + return edit; + } + } + }); + modalInstance.result.then((updated) => { + if (updated.Product.ProductID !== this.selectedInventory.Product.ProductID) { + const oldInventory = this.getOld(updated.Product.ProductID, this.voucher.Inventories); + if (!angular.isUndefined(oldInventory)) { + delete this.selectedInventory; + return false; + } + } + angular.copy(updated, this.selectedInventory); + delete this.selectedInventory; + }, () => { + delete this.selectedInventory; + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20, a: true}).$promise; + } + + products($viewValue) { + return this.Product.autocomplete({term: $viewValue, count: 20, a: true}).$promise; + } +} diff --git a/brewman/static/app/purchase/purchase.html b/brewman/static/app/purchase/purchase.html index 827d4422..61c3790d 100644 --- a/brewman/static/app/purchase/purchase.html +++ b/brewman/static/app/purchase/purchase.html @@ -7,7 +7,7 @@
@@ -15,10 +15,10 @@
-
+
@@ -28,24 +28,24 @@
- +
- +
- +
- +
- +
- +
@@ -62,7 +62,7 @@
- + @@ -71,12 +71,12 @@ @@ -89,14 +89,14 @@
- +
-
- - +
+ +
- - -
- Created on {{voucher.CreationDate | localTime}} and Last Edited on {{voucher.LastEditDate | localTime}} by - {{voucher.User.Name}}. Posted by {{voucher.Poster}} + Created on {{vm.voucher.CreationDate | localTime}} and Last Edited on {{vm.voucher.LastEditDate | localTime}} by + {{vm.voucher.User.Name}}. Posted by {{vm.voucher.Poster}}
\ No newline at end of file diff --git a/brewman/static/app/purchases/purchases.component.ts b/brewman/static/app/purchases/purchases.component.ts new file mode 100644 index 00000000..f8e55fbf --- /dev/null +++ b/brewman/static/app/purchases/purchases.component.ts @@ -0,0 +1,7 @@ +import {PurchasesController} from "./purchases.controller"; + +export const PurchasesComponent = { + templateUrl: '/app/purchases/purchases.html', + controller: PurchasesController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/purchases/purchases.controller.js b/brewman/static/app/purchases/purchases.controller.js deleted file mode 100644 index 28024db8..00000000 --- a/brewman/static/app/purchases/purchases.controller.js +++ /dev/null @@ -1,38 +0,0 @@ -angular - .module('overlord') - .controller('PurchasesController', PurchasesController); -PurchasesController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'purchases', 'uibDateParser']; -function PurchasesController($scope, $routeParams, $location, asDate, purchases, dateParser) { - var _info_StartDate = dateParser.parse(purchases.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(purchases.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = purchases; - $scope.show = function () { - $location.path('/Purchases').search({s: $scope.info.StartDate, f: $scope.info.FinishDate}); - }; -} -PurchasesController.resolve = { - purchases: ['$route', 'Purchases', function ($route, Purchases) { - var startDate = $route.current.params.s, - finishDate = $route.current.params.f; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return Purchases.get({}).$promise; - } else { - return Purchases.get({s: startDate, f: finishDate}).$promise; - } - }] -}; diff --git a/brewman/static/app/purchases/purchases.controller.ts b/brewman/static/app/purchases/purchases.controller.ts new file mode 100644 index 00000000..89df71d3 --- /dev/null +++ b/brewman/static/app/purchases/purchases.controller.ts @@ -0,0 +1,34 @@ +export class PurchasesController { + static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'uibDateParser']; + _info_StartDate: any; + _info_FinishDate: any; + info: any; + purchases: any; + + constructor(public $scope, public $routeParams, public $location, public asDate, public dateParser) { + this.purchases = $scope.$parent.res.purchases; + this._info_StartDate = dateParser.parse(this.purchases.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.purchases.FinishDate, "dd-MMM-yyyy"); + this.info = this.purchases; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/Purchases').search({s: this.info.StartDate, f: this.info.FinishDate}); + } +} diff --git a/brewman/static/app/purchases/purchases.html b/brewman/static/app/purchases/purchases.html index e71c1637..d7283b58 100644 --- a/brewman/static/app/purchases/purchases.html +++ b/brewman/static/app/purchases/purchases.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
@@ -39,7 +39,7 @@
- + @@ -47,7 +47,7 @@ - + diff --git a/brewman/static/app/purchases/purchases.resolver.ts b/brewman/static/app/purchases/purchases.resolver.ts new file mode 100644 index 00000000..91379a8c --- /dev/null +++ b/brewman/static/app/purchases/purchases.resolver.ts @@ -0,0 +1,12 @@ +import * as angular from 'angular'; + +export function PurchasesResolver($route, Purchases) { + const startDate = $route.current.params.s, + finishDate = $route.current.params.f; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return Purchases.get({}).$promise; + } else { + return Purchases.get({s: startDate, f: finishDate}).$promise; + } +} diff --git a/brewman/static/app/purchases/purchases.service.ts b/brewman/static/app/purchases/purchases.service.ts new file mode 100644 index 00000000..b85ad9a6 --- /dev/null +++ b/brewman/static/app/purchases/purchases.service.ts @@ -0,0 +1,3 @@ +export function Purchases($resource) { + return $resource('/api/Purchases'); +} diff --git a/brewman/static/app/raw-material-cost/raw-material-cost-detail.html b/brewman/static/app/raw-material-cost/raw-material-cost-detail.html index 93f78b6c..7e8f5258 100644 --- a/brewman/static/app/raw-material-cost/raw-material-cost-detail.html +++ b/brewman/static/app/raw-material-cost/raw-material-cost-detail.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
Amount
{{items.Date}} {{items.Supplier}}
{{inventory.Product.Name}} {{inventory.Quantity | number:2}} {{inventory.Rate | currency}}{{inventory.Amount | currency}}
{{inventory.Product.Name}} {{inventory.Quantity | number:2}} {{inventory.Rate | currency}}{{inventory.Amount | currency}}
{{item.Name}} {{item.Quantity | number:2 | clr}} {{item.Rate | currency | clr}}
{{item.Name}} {{item.Quantity | number:2 | clr}} {{item.Rate | currency | clr}}
@@ -39,7 +39,7 @@ - + diff --git a/brewman/static/app/raw-material-cost/raw-material-cost.component.ts b/brewman/static/app/raw-material-cost/raw-material-cost.component.ts new file mode 100644 index 00000000..0ff5aee5 --- /dev/null +++ b/brewman/static/app/raw-material-cost/raw-material-cost.component.ts @@ -0,0 +1,7 @@ +import {RawMaterialCostController} from "./raw-material-cost.controller"; + +export const RawMaterialCostComponent = { + templateUrl: '/app/raw-material-cost/raw-material-cost.html', + controller: RawMaterialCostController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/raw-material-cost/raw-material-cost.controller.js b/brewman/static/app/raw-material-cost/raw-material-cost.controller.js deleted file mode 100644 index 1708f72f..00000000 --- a/brewman/static/app/raw-material-cost/raw-material-cost.controller.js +++ /dev/null @@ -1,46 +0,0 @@ -angular - .module('overlord') - .controller('RawMaterialCostController', RawMaterialCostController); -RawMaterialCostController.$inject = ['$scope', '$location', 'asDateFilter', 'rawMaterialCost', 'uibDateParser']; -function RawMaterialCostController($scope, $location, asDate, rawMaterialCost, dateParser) { - var _info_StartDate = dateParser.parse(rawMaterialCost.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(rawMaterialCost.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = rawMaterialCost; - $scope.show = function () { - $location.path('/RawMaterialCost').search({ - StartDate: $scope.info.StartDate, - FinishDate: $scope.info.FinishDate - }); - }; - $scope.foDate = true; -} - -RawMaterialCostController.resolve = { - rawMaterialCost: ['$route', 'RawMaterialCost', function ($route, RawMaterialCost) { - var id = $route.current.params.id, - startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return RawMaterialCost.get({}).$promise; - } else if (angular.isUndefined(id)) { - return RawMaterialCost.get({StartDate: startDate, FinishDate: finishDate}).$promise; - } else { - return RawMaterialCost.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; diff --git a/brewman/static/app/raw-material-cost/raw-material-cost.controller.ts b/brewman/static/app/raw-material-cost/raw-material-cost.controller.ts new file mode 100644 index 00000000..bbb5bb62 --- /dev/null +++ b/brewman/static/app/raw-material-cost/raw-material-cost.controller.ts @@ -0,0 +1,39 @@ +export class RawMaterialCostController { + static $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + _info_StartDate: any; + _info_FinishDate: any; + info: any; + foDate: any; + rawMaterialCost: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.rawMaterialCost = $scope.$parent.res.rawMaterialCost; + this._info_StartDate = dateParser.parse(this.rawMaterialCost.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.rawMaterialCost.FinishDate, "dd-MMM-yyyy"); + this.info = this.rawMaterialCost; + this.foDate = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/RawMaterialCost').search({ + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }); + } +} diff --git a/brewman/static/app/raw-material-cost/raw-material-cost.html b/brewman/static/app/raw-material-cost/raw-material-cost.html index cd03b5e8..2ea8da71 100644 --- a/brewman/static/app/raw-material-cost/raw-material-cost.html +++ b/brewman/static/app/raw-material-cost/raw-material-cost.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
{{item.Name}} {{item.Group}} {{item.Quantity | number:2}}
@@ -38,7 +38,7 @@ - + @@ -46,7 +46,7 @@ - + diff --git a/brewman/static/app/raw-material-cost/raw-material-cost.resolver.ts b/brewman/static/app/raw-material-cost/raw-material-cost.resolver.ts new file mode 100644 index 00000000..3f6e987b --- /dev/null +++ b/brewman/static/app/raw-material-cost/raw-material-cost.resolver.ts @@ -0,0 +1,15 @@ +import * as angular from 'angular'; + +export function RawMaterialCostResolver($route, RawMaterialCost) { + const id = $route.current.params.id, + startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return RawMaterialCost.get({}).$promise; + } else if (angular.isUndefined(id)) { + return RawMaterialCost.get({StartDate: startDate, FinishDate: finishDate}).$promise; + } else { + return RawMaterialCost.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/raw-material-cost/raw-material-cost.service.ts b/brewman/static/app/raw-material-cost/raw-material-cost.service.ts new file mode 100644 index 00000000..536bd6f3 --- /dev/null +++ b/brewman/static/app/raw-material-cost/raw-material-cost.service.ts @@ -0,0 +1,3 @@ +export function RawMaterialCost($resource) { + return $resource('/api/RawMaterialCost/:id'); +} diff --git a/brewman/static/app/receipt/receipt-modal.controller.js b/brewman/static/app/receipt/receipt-modal.controller.js deleted file mode 100644 index 9a3e7380..00000000 --- a/brewman/static/app/receipt/receipt-modal.controller.js +++ /dev/null @@ -1,17 +0,0 @@ -angular - .module('overlord') - .controller('ReceiptModalController', ReceiptModalController); -ReceiptModalController.$inject = ['$scope', '$uibModalInstance', 'mathSolver', 'edit', 'Account']; -function ReceiptModalController($scope, $modalInstance, mathSolver, edit, Account) { - $scope.edit = edit; - $scope.ok = function () { - $scope.edit.Amount = mathSolver($scope.edit.Amount); - $modalInstance.close($scope.edit); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} diff --git a/brewman/static/app/receipt/receipt-modal.controller.ts b/brewman/static/app/receipt/receipt-modal.controller.ts new file mode 100644 index 00000000..9a7e1448 --- /dev/null +++ b/brewman/static/app/receipt/receipt-modal.controller.ts @@ -0,0 +1,21 @@ +export class ReceiptModalController { + static $inject = ['$scope', '$uibModalInstance', 'MathSolver', 'Account']; + edit:any; + + constructor(public $scope, public $modalInstance, public MathSolver, public Account) { + this.edit = $scope.$resolve.edit; + } + + ok() { + this.edit.Amount = this.MathSolver(this.edit.Amount); + this.$modalInstance.close(this.edit); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/receipt/receipt-modal.html b/brewman/static/app/receipt/receipt-modal.html index 0607bb96..d4c3a98c 100644 --- a/brewman/static/app/receipt/receipt-modal.html +++ b/brewman/static/app/receipt/receipt-modal.html @@ -8,20 +8,20 @@
-
+ ng-model="vmModal.edit.Amount"/>
diff --git a/brewman/static/app/receipt/receipt-voucher.resolver.ts b/brewman/static/app/receipt/receipt-voucher.resolver.ts new file mode 100644 index 00000000..94a2edb4 --- /dev/null +++ b/brewman/static/app/receipt/receipt-voucher.resolver.ts @@ -0,0 +1,16 @@ +import * as angular from 'angular'; + +export function ReceiptVoucherResolver($route, Voucher) { + const id = $route.current.params.id, + account = $route.current.params.a; + + if (angular.isUndefined(id)) { + let options = {type: 'Receipt'}; + if (!angular.isUndefined(account)) { + options['a'] = account; + } + return Voucher.get(options).$promise; + } else { + return Voucher.get({id: id}).$promise; + } +} diff --git a/brewman/static/app/receipt/receipt.component.ts b/brewman/static/app/receipt/receipt.component.ts new file mode 100644 index 00000000..dcb08ac4 --- /dev/null +++ b/brewman/static/app/receipt/receipt.component.ts @@ -0,0 +1,7 @@ +import {ReceiptController} from "./receipt.controller"; + +export const ReceiptComponent = { + templateUrl: '/app/receipt/receipt.html', + controller: ReceiptController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/receipt/receipt.controller.js b/brewman/static/app/receipt/receipt.controller.js deleted file mode 100644 index 8735bcea..00000000 --- a/brewman/static/app/receipt/receipt.controller.js +++ /dev/null @@ -1,215 +0,0 @@ -angular - .module('overlord') - .controller('ReceiptController', ReceiptController); -ReceiptController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', '$uibModal', 'uploadedImageResizer', 'mathSolver', 'voucher', 'ledgers', 'Voucher', 'Account', 'uibDateParser']; -function ReceiptController($scope, $routeParams, $location, asDate, $modal, uploadedImageResizer, mathSolver, voucher, ledgers, Voucher, Account, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.foAccount = true; - $scope.voucher = voucher; - $scope.ledgers = ledgers; - function getOld(ledgerID, journals) { - return _.find(journals, function (journal) { - return journal.Ledger.LedgerID === ledgerID; - }); - } - - $scope.$on("fileSelected", function (event, args) { - uploadedImageResizer(args, $scope.voucher.Files); - }); - - - $scope.deleteFile = function (item) { - var index = $scope.voucher.Files.indexOf(item); - $scope.voucher.Files.splice(index, 1); - }; - - $scope.zoomImage = function (item) { - $modal.open({ - templateUrl: '/template/modal/image.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.imageUrl = item.Resized; - $scope.size = null; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - }; - - $scope.add = function () { - var amount, - oldJournal; - if (!$scope.account || !$scope.account.LedgerID) { - return; - } - amount = mathSolver($scope.amount); - if (Number.isNaN(amount) || amount <= 0) { - return; - } - oldJournal = getOld($scope.account.LedgerID, $scope.voucher.Journals); - if (angular.isUndefined(oldJournal)) { - $scope.voucher.Journals.push({Debit: -1, Amount: amount, Ledger: $scope.account}); - } else { - if (oldJournal.Debit === -1) { - oldJournal.Amount += amount; - } else { - return; - } - } - delete $scope.account; - delete $scope.amount; - $scope.foAccount = true; - }; - - $scope.removeJournal = function (journal) { - var index = $scope.voucher.Journals.indexOf(journal); - $scope.voucher.Journals.splice(index, 1); - }; - - $scope.$watch('voucher.Journals', function (journals, oldValue) { - var amount = _.chain(journals) - .filter({'Debit': -1}) - .reduce(function (sum, item) { - return item.Amount + sum; - }, 0).value(); - - var j = _.find(journals, {'Debit': 1}); - j.Amount = amount; - if (_.find(oldValue, {'Debit': 1}).Ledger.LedgerID !== j.Ledger.LedgerID) { - $location.search({a: j.Ledger.LedgerID}).replace(); - } - }, true); - - $scope.$watch('account', function (account) { - if (!account) { - delete $scope.accBal; - } - else { - Account.balance({id: account.LedgerID, d: $scope.voucher.Date}, function (bal) { - $scope.accBal = bal; - }); - } - }, true); - - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined($scope.perms)) { - return false; - } else if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Receipt']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID != $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.save = function () { - return $scope.voucher.$save({type: 'Receipt'}, function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Receipt/' + u.VoucherID); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.voucher.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Receipt').replace(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.post = function () { - return $scope.voucher.$post(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.modal = function (journal) { - $scope.selectedJournal = journal; - var edit = {}; - angular.copy($scope.selectedJournal, edit); - var modalInstance = $modal.open({ - backdrop: true, - size: 'lg', - templateUrl: '/app/receipt/receipt-modal.html', - controller: ReceiptModalController, - resolve: { - edit: function () { - return edit; - } - } - }); - modalInstance.result.then(function (updated) { - if (updated.Ledger.LedgerID !== $scope.selectedJournal.Ledger.LedgerID) { - var oldJournal = getOld(updated.Ledger.LedgerID, $scope.voucher.Journals); - if (!angular.isUndefined(oldJournal)) { - delete $scope.selectedJournal; - return false; - } - } - angular.copy(updated, $scope.selectedJournal); - delete $scope.selectedJournal; - }, function () { - delete $scope.selectedJournal; - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20, 'a': true}).$promise; - }; -} - -ReceiptController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id, - account = $route.current.params.a; - - if (angular.isUndefined(id)) { - var options = {type: 'Receipt'}; - if (!angular.isUndefined(account)) { - options.a = account; - } - return Voucher.get(options).$promise; - } else { - return Voucher.get({id: id}).$promise; - } - }], - ledgers: ['Account', function (Account) { - return Account.autocomplete({term: '', type: 1}).$promise; - }] -}; diff --git a/brewman/static/app/receipt/receipt.controller.ts b/brewman/static/app/receipt/receipt.controller.ts new file mode 100644 index 00000000..a3270b74 --- /dev/null +++ b/brewman/static/app/receipt/receipt.controller.ts @@ -0,0 +1,222 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import {ReceiptModalController} from './receipt-modal.controller'; + +export class ReceiptController { + static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', '$uibModal', 'UploadedImageResizer', 'MathSolver', 'Voucher', 'Account', 'uibDateParser', 'Messages', 'Credentials']; + _voucher_Date: any; + foAccount: any; + selectedJournal: any; + accBal: any; + account: any; + amount: any; + voucher: any; + ledgers: any; + + constructor(public $scope, public $routeParams, public $location, public asDate, public $modal, public UploadedImageResizer, public MathSolver, public Voucher, public Account, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this.ledgers = $scope.$parent.res.ledgers; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + this.foAccount = true; + + $scope.$on("fileSelected", (event, args) => { + UploadedImageResizer(args, this.voucher.Files); + }); + $scope.$watch('vm.voucher.Journals', function (journals, oldValue) { + const amount = _.chain(journals) + .filter({'Debit': -1}) + .reduce(function (sum, item) { + return item.Amount + sum; + }, 0).value(); + + let j = _.find(journals, {'Debit': 1}); + j.Amount = amount; + if (_.find(oldValue, {'Debit': 1}).Ledger.LedgerID !== j.Ledger.LedgerID) { + $location.search({a: j.Ledger.LedgerID}).replace(); + } + }, true); + + $scope.$watch('vm.account', (account) => { + if (!account) { + delete this.accBal; + } + else { + Account.balance({id: account.LedgerID, d: this.voucher.Date}, (bal) => { + this.accBal = bal; + }); + } + }, true); + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + getOld(ledgerID, journals) { + return _.find(journals, function (journal) { + return journal.Ledger.LedgerID === ledgerID; + }); + } + + deleteFile(item) { + const index = this.voucher.Files.indexOf(item); + this.voucher.Files.splice(index, 1); + } + + zoomImage(item) { + this.$modal.open({ + templateUrl: '/template/modal/image.html', + controller: ['$uibModalInstance', class { + imageUrl: any; + size: any; + + constructor(public $modalInstance) { + this.imageUrl = item.Resized; + this.size = null; + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + } + + add() { + let amount, + oldJournal; + if (!this.account || !this.account.LedgerID) { + return; + } + amount = this.MathSolver(this.amount); + if (Number.isNaN(amount) || amount <= 0) { + return; + } + oldJournal = this.getOld(this.account.LedgerID, this.voucher.Journals); + if (angular.isUndefined(oldJournal)) { + this.voucher.Journals.push({Debit: -1, Amount: amount, Ledger: this.account}); + } else { + if (oldJournal.Debit === -1) { + oldJournal.Amount += amount; + } else { + return; + } + } + delete this.account; + delete this.amount; + this.foAccount = true; + } + + removeJournal(journal) { + const index = this.voucher.Journals.indexOf(journal); + this.voucher.Journals.splice(index, 1); + } + + preventAlteration(voucher) { + if (angular.isUndefined(this.Credentials.Perms)) { + return false; + } else if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Receipt']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID != this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + save() { + return this.voucher.$save({type: 'Receipt'}, (u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Receipt/' + u.VoucherID); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.voucher.$delete((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Receipt').replace(); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + post() { + return this.voucher.$post((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + modal(journal) { + this.selectedJournal = journal; + let edit = {}; + angular.copy(this.selectedJournal, edit); + const modalInstance = this.$modal.open({ + backdrop: true, + size: 'lg', + templateUrl: '/app/receipt/receipt-modal.html', + controllerAs: 'vmModal', + controller: ReceiptModalController, + resolve: { + edit: function () { + return edit; + } + } + }); + modalInstance.result.then((updated) => { + if (updated.Ledger.LedgerID !== this.selectedJournal.Ledger.LedgerID) { + let oldJournal = this.getOld(updated.Ledger.LedgerID, this.voucher.Journals); + if (!angular.isUndefined(oldJournal)) { + delete this.selectedJournal; + return false; + } + } + angular.copy(updated, this.selectedJournal); + delete this.selectedJournal; + }, () => { + delete this.selectedJournal; + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20, 'a': true}).$promise; + } +} diff --git a/brewman/static/app/receipt/receipt.html b/brewman/static/app/receipt/receipt.html index e7d52dec..a0aaefc3 100644 --- a/brewman/static/app/receipt/receipt.html +++ b/brewman/static/app/receipt/receipt.html @@ -7,7 +7,7 @@
@@ -15,10 +15,10 @@
-
+
@@ -29,20 +29,20 @@
- + -

Balance as on Date: {{accBal.Date | accounting}} / {{accBal.Total +

Balance as on Date: {{vm.accBal.Date | accounting}} / {{vm.accBal.Total | accounting}}

+ ng-model="vm.amount" on-return="vm.add()"/> -
@@ -57,17 +57,17 @@
- + @@ -80,14 +80,14 @@
- +
-
- - +
+ +
{{item.Name}} {{item.Issue | currency}} {{item.Sale | currency}}
{{item.Name}} {{item.Issue | currency}} {{item.Sale | currency}}
{{journal.Ledger.Name}} {{journal.Amount | currency}}
@@ -76,12 +76,12 @@ - +
{{item.Product.Name}} {{item.Quantity | number:2}} {{item.Product.FractionUnits}} ₹ {{item.Price}} / {{item.Product.Units}} of {{item.Product.Fraction}} - {{product.FractionUnits}} + {{vm.product.FractionUnits}} Yield {{item.Product.ProductYield * 100 | number:2}}% @@ -90,13 +90,13 @@ item.Product.ProductYield)) | currency}} - +
- Save - Delete + Save + Delete
diff --git a/brewman/static/app/recipe/recipe-list.controller.js b/brewman/static/app/recipe/recipe-list.controller.js deleted file mode 100644 index 1cb55db3..00000000 --- a/brewman/static/app/recipe/recipe-list.controller.js +++ /dev/null @@ -1,124 +0,0 @@ -angular - .module('overlord') - .controller('RecipeListController', RecipeListController); -RecipeListController.$inject = ['$scope', 'recipes', '$location', '$routeParams', '$filter', 'Tokenizer']; -function RecipeListController($scope, recipes, $location, $routeParams, $filter, Tokenizer) { - $scope.info = recipes; - $scope.search = $routeParams.q || ''; - $scope.product_groups = _.reduce(recipes, function (acculumator, item) { - if (!acculumator.includes(item.ProductGroup)){ - acculumator.push(item.ProductGroup); - } - return acculumator; - },[]).sort(); - - $scope.startDate = function (startDate) { - if (arguments.length === 0) { - return $scope._startDate; - } - $scope._startDate = startDate; - var re = /(('[s]'|"[s]"|[s]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, - matches = $scope.search.match(re), - st = startDate === null ? '' : 's:>=' + moment(startDate).format('DD-MMM-YYYY'); - $scope.search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st); - }; - - $scope.finishDate = function (finishDate) { - if (arguments.length === 0) { - return $scope._finishDate; - } - $scope._finishDate = finishDate; - var re = /(('[f]'|"[f]"|[f]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, - matches = $scope.search.match(re), - st = finishDate === null ? '' : 'f:<=' + moment(finishDate).format('DD-MMM-YYYY'); - $scope.search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st); - }; - - $scope.productGroup = function (productGroup) { - if (arguments.length === 0) { - - return $scope._productGroup; - } - $scope._productGroup = productGroup; - var re = /(('[t]'|"[t]"|[t]+)\s*:\s*('[^']+'|"[^"]+"|[^\s]+))/gi, - matches = $scope.search.match(re), - st = 't:"' + productGroup + '"', - search = (matches === null) ? $scope.search.trim() + ' ' + st : $scope.search.replace(re, st); - $scope.search = search.trim(); - }; - - $scope.$watch('search', function (value) { - $scope.filterRecipes(value); - }, true); - - $scope.$on('$destroy', function () { - Tokenizer.doFilter.cache = {}; - }); - - $scope.searchInfo = { - comparator: { - 'n': {'Col': 'Name', 'Comparator': 'text'}, - 't': {'Col': 'ProductGroup', 'Comparator': 'text'}, - 's': {'Col': 'Prices.ValidFrom', 'Comparator': 'date'}, - 'f': {'Col': 'Prices.ValidTo', 'Comparator': 'date'} - }, - def: 'n', - sorter: { - 'n': 'Name', - 't': 'ProductGroup', - 's': 'Prices.ValidFrom', - 'f': 'Prices.ValidTo', - 'c': 'Prices.Costing', - 'cp': 'Prices.CostPrice', - 'sp': 'Prices.SalePrice' - }, - flags: {} - }; - - $scope.filterRecipes = _.debounce(function (q) { - if (q !== $scope._search) { - $scope._search = q; - if (angular.isUndefined(q) || q === '') { - $location.path('/Recipes').search('q', null).replace(); - } else { - $location.path('/Recipes').search({'q': q}).replace(); - } - $scope.$apply(function () { - $scope.recipes = $scope.doFilter(q); - }); - } - }, 350); - $scope.doFilter = function (q) { - var matches = Tokenizer.parseFilterString(q, $scope.searchInfo), - array = angular.copy($scope.info); - - array = $scope.subFilter(null, array, matches.q, matches.o); - array.forEach(function (prod) { - prod.Prices = $scope.subFilter('Prices.', prod.Prices, matches.q, matches.o); - }); - return array; - }; - - $scope.subFilter = function (prefix, arr, q, o) { - q = angular.copy(q); - o = angular.copy(o); - if (prefix === null) { - q = q.filter(x => !x.Col.includes('.')); - o = o.filter(x => !x.includes('.')); - } else { - q = q.filter(x => x.Col.startsWith(prefix)); - q.forEach(function (x) {x.Col = x.Col.substr(prefix.length)}); - o = o.filter(x => x.substr(1).startsWith(prefix)).map(x => x[0] + x.substr(prefix.length + 1)); - } - if (q.length !== 0) { - arr = arr.filter(item => q.every(exp => exp.Comparator(item[exp.Col], exp.Value))); - } - return $filter('orderBy')(arr, o); - } -} - -RecipeListController.resolve = { - recipes: ['Recipe', function (Recipe) { - return Recipe.query({}).$promise; - }] -}; diff --git a/brewman/static/app/recipe/recipe-list.html b/brewman/static/app/recipe/recipe-list.html index a4ab179b..30cd8960 100644 --- a/brewman/static/app/recipe/recipe-list.html +++ b/brewman/static/app/recipe/recipe-list.html @@ -1,7 +1,7 @@

Recipes

- + Add
-
-
- - {{pg}} + + {{pg}}
@@ -38,7 +38,7 @@ Costing - + {{items.Name}} {{items.ProductGroup}} diff --git a/brewman/static/app/recipe/recipe.controller.js b/brewman/static/app/recipe/recipe.controller.js deleted file mode 100644 index 197763de..00000000 --- a/brewman/static/app/recipe/recipe.controller.js +++ /dev/null @@ -1,117 +0,0 @@ -angular - .module('overlord') - .controller('RecipeController', RecipeController); -RecipeController.$inject = ['$scope', '$location', '$window', '$uibModal', 'asDateFilter', 'Product', 'recipe']; -function RecipeController($scope, $location, $window, $modal, asDate, Product, recipe) { - recipe.ValidFrom = moment(recipe.ValidFrom, 'DD-MMM-YYYY').toDate(); - recipe.ValidTo = moment(recipe.ValidTo, 'DD-MMM-YYYY').toDate(); - $scope.recipe = recipe; - $scope.foIngredient = recipe.RecipeItems > 0; - - $scope.costPrice = 0; - function getOld(productID, recipeItems) { - return _.find(recipeItems, function (recipe_item) { - return recipe_item.Product.ProductID === productID; - }); - } - - $scope.add = function () { - if (!$scope.product || !$scope.product.ProductID || !$scope.quantity || Number(!$scope.quantity)) { - return; - } - var oldItem = getOld($scope.product.ProductID, $scope.recipe.RecipeItems); - if (angular.isUndefined(oldItem)) { - var quantity = Number($scope.quantity); - var price = Number($scope.product.Price); - $scope.recipe.RecipeItems.push({ - Product: $scope.product, - Quantity: quantity, - Price: price - }); - } else { - $scope.toasts.push({Type: 'Danger', Message: 'Ingredient already in the list'}); - } - delete $scope.quantity; - delete $scope.product; - $scope.searchIngredient = ''; - $scope.foIngredient = true; - }; - - $scope.removeItem = function (item) { - var index = $scope.recipe.RecipeItems.indexOf(item); - $scope.recipe.RecipeItems.splice(index, 1); - }; - - $scope.$watch('recipe.RecipeItems', function (recipeItems) { - if (!angular.isArray(recipeItems)) { - return; - } - $scope.costPrice = recipeItems.reduce(function (sum, item) { - var rate = item.Price / (item.Product.Fraction * item.Product.ProductYield); - return sum + (item.Quantity * rate); - }, 0); - }, true); - - $scope.save = function () { - if (angular.isUndefined($scope.recipe.ValidFrom) || $scope.recipe.ValidFrom === '') { - $scope.toasts.push({Type: 'Danger', Message: 'Please Choose a proper validity period'}); - return; - } - if (angular.isUndefined($scope.recipe.ValidTo) || $scope.recipe.ValidTo === '') { - $scope.toasts.push({Type: 'Danger', Message: 'Please Choose a proper validity period'}); - return; - } - $scope.recipe.$save(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $window.history.back(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.recipe.$delete(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $window.history.back(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Recipe"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - $scope.products = function ($viewValue, options) { - return Product.autocomplete(angular.extend({ - term: $viewValue, - count: 20, - a: true, - e: true - }, options)).$promise; - }; -} - -RecipeController.resolve = { - recipe: ['$route', 'Recipe', function ($route, Recipe) { - var id = $route.current.params.id; - - return Recipe.get({id: id}).$promise; - }] -}; diff --git a/brewman/static/app/recipe/recipe.service.ts b/brewman/static/app/recipe/recipe.service.ts new file mode 100644 index 00000000..3ceb7cd0 --- /dev/null +++ b/brewman/static/app/recipe/recipe.service.ts @@ -0,0 +1,6 @@ +export function Recipe($resource) { + return $resource('/api/Recipe/:id', + {id: '@RecipeID'}, { + query: {method: 'GET', params: {list: true}, isArray: true} + }); +} diff --git a/brewman/static/app/reconcile/reconcile.component.ts b/brewman/static/app/reconcile/reconcile.component.ts new file mode 100644 index 00000000..64ab838c --- /dev/null +++ b/brewman/static/app/reconcile/reconcile.component.ts @@ -0,0 +1,7 @@ +import {ReconcileController} from "./reconcile.controller"; + +export const ReconcileComponent = { + templateUrl: '/app/reconcile/reconcile.html', + controller: ReconcileController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/reconcile/reconcile.controller.js b/brewman/static/app/reconcile/reconcile.controller.js deleted file mode 100644 index 4b9a10ec..00000000 --- a/brewman/static/app/reconcile/reconcile.controller.js +++ /dev/null @@ -1,152 +0,0 @@ -angular - .module('overlord') - .controller('ReconcileController', ReconcileController); -ReconcileController.$inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'reconcile', 'Reconcile', 'Account', 'uibDateParser']; -function ReconcileController($scope, $routeParams, $location, asDate, reconcile, Reconcile, Account, dateParser) { - var _info_StartDate = dateParser.parse(reconcile.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(reconcile.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = reconcile; - $scope.show = function () { - var id = $scope.info.Account.LedgerID; - if (id === $routeParams.id && $scope.info.StartDate === $routeParams.StartDate && $scope.info.FinishDate === $routeParams.FinishDate) { - Reconcile.get({ - id: id, - StartDate: $scope.info.StartDate, - FinishDate: $scope.info.FinishDate - }, function (data) { - $scope.info = data; - }); - } else { - $location.path('/Reconcile/' + id).search('StartDate', startDate).search('FinishDate', finishDate); - } - }; - - $scope.save = function () { - var i, - len = $scope.body.length; - $scope.info.Body = $scope.body; - $scope.info.$save({ - StartDate: $routeParams.StartDate, - FinishDate: $routeParams.FinishDate - }, function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $scope.info = u; - $scope.doFilter(); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.downloadTable = function () { - var table = $('#gvGrid'), - html = table.clone().wrap('
').parent().html(); - html = html.replace(/á/g, 'á'); - window.open('data:application/vnd.ms-excel;charset=UTF-8,' + encodeURIComponent(html)); - }; - - if ($routeParams.id) { - $scope.foGrid = true; - } else { - $scope.foLedger = true; - } - - $scope.selected = -1; - $scope.setSelected = function (index) { - $scope.selected = index; - }; - - $scope.doFilter = function () { - var data = angular.copy($scope.info.Body), - debit = 0, credit = 0, running = 0; - - data = data.sort(function (a, b) { - if (a.IsReconciled !== b.IsReconciled) { - return b.IsReconciled - a.IsReconciled; - } - var aDate = moment(a.ReconcileDate, 'DD-MMM-YYYY'); - var bDate = moment(b.ReconcileDate, 'DD-MMM-YYYY'); - return aDate - bDate; - }); - - _.forEach(data, function (item) { - if (item.Type !== 'Opening Balance') { - debit += item.Debit; - credit += item.Credit; - if (item.IsReconciled) { - running += item.Debit - item.Credit; - } - } else { - running += item.Debit - item.Credit; - } - item.Running = running; - }); - $scope.body = data; - $scope.footer = { - Debit: debit, - Credit: credit, - Running: running - } - }; - - $scope.doFilter(); - - $scope.shortcuts = { - 'up': function (e) { - if ($scope.selected > 0) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected - 1), $scope.body.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - }, - 'down': function (e) { - if ($scope.selected < $scope.info.Body.length - 1) { - $scope.$apply(function () { - $scope.selected = Math.min(Math.max(0, $scope.selected + 1), $scope.body.length - 1); - }); - $("#" + $scope.selected).scrollintoview(); - e.preventDefault(); - } - }, - 'enter': function (e) { - var path = $scope.body[$scope.selected].Url.replace(/^(?:\/\/|[^\/]+)*/, ""); - $scope.$apply(function () { - $location.path(path).search('StartDate', null).search('FinishDate', null); - }); - e.preventDefault(); - } - }; - - $scope.accounts = function ($viewValue) { - return Account.autocomplete({term: $viewValue, count: 20, r: true}).$promise; - }; -} - -ReconcileController.resolve = { - reconcile: ['$route', 'Reconcile', function ($route, Reconcile) { - var id = $route.current.params.id, - startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(id)) { - return Reconcile.get({}).$promise; - } else { - return Reconcile.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; diff --git a/brewman/static/app/reconcile/reconcile.controller.ts b/brewman/static/app/reconcile/reconcile.controller.ts new file mode 100644 index 00000000..393b5e9f --- /dev/null +++ b/brewman/static/app/reconcile/reconcile.controller.ts @@ -0,0 +1,157 @@ +import * as angular from 'angular'; +import * as _ from 'lodash'; +import * as $ from 'jquery'; +import * as moment from 'moment'; + +export class ReconcileController { + static $inject = ['$scope', '$routeParams', '$location', 'asDateFilter', 'Reconcile', 'Account', 'uibDateParser', 'Messages']; + _info_StartDate: any; + _info_FinishDate: any; + info: any; + foGrid: any; + foLedger: any; + selected: any; + body: any; + footer: any; + shortcuts: any; + reconcile: any; + + constructor(public $scope, public $routeParams, public $location, public asDate, public Reconcile, public Account, public dateParser, public Messages) { + this.reconcile = $scope.$parent.res.reconcile; + this._info_StartDate = dateParser.parse(this.reconcile.StartDate, "dd-MMM-yyyy") + this._info_FinishDate = dateParser.parse(this.reconcile.FinishDate, "dd-MMM-yyyy"); + this.info = this.reconcile; + if ($routeParams.id) { + this.foGrid = true; + } else { + this.foLedger = true; + } + + this.selected = -1; + + this.doFilter(); + + this.shortcuts = { + 'up': (e) => { + if (this.selected > 0) { + $scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected - 1), this.body.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + }, + 'down': (e) => { + if (this.selected < this.info.Body.length - 1) { + $scope.$apply(() => { + this.selected = Math.min(Math.max(0, this.selected + 1), this.body.length - 1); + }); + $("#" + this.selected).scrollintoview(); + e.preventDefault(); + } + }, + 'enter': (e) => { + const path = this.body[this.selected].Url.replace(/^(?:\/\/|[^\/]+)*/, ""); + $scope.$apply(() => { + this.$location.path(path).search('StartDate', null).search('FinishDate', null); + }); + e.preventDefault(); + } + }; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + const id = this.info.Account.LedgerID; + if (id === this.$routeParams.id && this.info.StartDate === this.$routeParams.StartDate && this.info.FinishDate === this.$routeParams.FinishDate) { + this.Reconcile.get({ + id: id, + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }, (data) => { + this.info = data; + }); + } else { + this.$location.path('/Reconcile/' + id).search('StartDate', this.info.StartDate).search('FinishDate', this.info.FinishDate); + } + } + + save() { + let i, + len = this.body.length; + this.info.Body = this.body; + this.info.$save({ + StartDate: this.$routeParams.StartDate, + FinishDate: this.$routeParams.FinishDate + }, (u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.info = u; + this.doFilter(); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + downloadTable() { + let table = $('#gvGrid'), + html = table.clone().wrap('
').parent().html(); + html = html.replace(/á/g, 'á'); + window.open('data:application/vnd.ms-excel;charset=UTF-8,' + encodeURIComponent(html)); + } + + setSelected(index) { + this.selected = index; + } + + doFilter() { + let data = angular.copy(this.info.Body), + debit = 0, credit = 0, running = 0; + + data = data.sort(function (a, b) { + if (a.IsReconciled !== b.IsReconciled) { + return b.IsReconciled - a.IsReconciled; + } + const aDate: any = moment(a.ReconcileDate, 'DD-MMM-YYYY'); + const bDate: any = moment(b.ReconcileDate, 'DD-MMM-YYYY'); + return aDate - bDate; + }); + + _.forEach(data, function (item) { + if (item.Type !== 'Opening Balance') { + debit += item.Debit; + credit += item.Credit; + if (item.IsReconciled) { + running += item.Debit - item.Credit; + } + } else { + running += item.Debit - item.Credit; + } + item.Running = running; + }); + this.body = data; + this.footer = { + Debit: debit, + Credit: credit, + Running: running + } + } + + accounts($viewValue) { + return this.Account.autocomplete({term: $viewValue, count: 20, r: true}).$promise; + } +} diff --git a/brewman/static/app/reconcile/reconcile.html b/brewman/static/app/reconcile/reconcile.html index 63c48fcd..a8003b6c 100644 --- a/brewman/static/app/reconcile/reconcile.html +++ b/brewman/static/app/reconcile/reconcile.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -30,17 +30,17 @@
- + -
- +
@@ -51,8 +51,8 @@ - - + + @@ -64,7 +64,7 @@ @@ -73,7 +73,7 @@ - - - - + + +
DateReconcile Date
{{item.Date}} {{item.Name}} {{item.Debit | currency | clr}}
+

{{item.Narration}}

{{item.Type}} @@ -85,17 +85,17 @@
{{footer.Debit | currency}}{{footer.Credit | currency}}{{footer.Running | accounting}}{{vm.footer.Debit | currency}}{{vm.footer.Credit | currency}}{{vm.footer.Running | accounting}}
- - +
diff --git a/brewman/static/app/reconcile/reconcile.resolver.ts b/brewman/static/app/reconcile/reconcile.resolver.ts new file mode 100644 index 00000000..f9c4d7a3 --- /dev/null +++ b/brewman/static/app/reconcile/reconcile.resolver.ts @@ -0,0 +1,13 @@ +import * as angular from 'angular'; + +export function ReconcileResolver($route, Reconcile) { + const id = $route.current.params.id, + startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(id)) { + return Reconcile.get({}).$promise; + } else { + return Reconcile.get({id: id, StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/reconcile/reconcile.service.ts b/brewman/static/app/reconcile/reconcile.service.ts new file mode 100644 index 00000000..51fbc92d --- /dev/null +++ b/brewman/static/app/reconcile/reconcile.service.ts @@ -0,0 +1,3 @@ +export function Reconcile($resource) { + return $resource('/api/Reconcile/:id', {id: '@Account.LedgerID'}); +} diff --git a/brewman/static/app/salary-deduction/salary-deduction-voucher.resolver.ts b/brewman/static/app/salary-deduction/salary-deduction-voucher.resolver.ts new file mode 100644 index 00000000..70ccfe01 --- /dev/null +++ b/brewman/static/app/salary-deduction/salary-deduction-voucher.resolver.ts @@ -0,0 +1,11 @@ +import * as angular from 'angular'; + +export function SalaryDeductionVoucherResolver($route, Voucher) { + const id = $route.current.params.id; + + if (angular.isUndefined(id)) { + return Voucher.get({type: 'Salary Deduction'}).$promise; + } else { + return Voucher.get({id: id}).$promise; + } +} \ No newline at end of file diff --git a/brewman/static/app/salary-deduction/salary-deduction.component.ts b/brewman/static/app/salary-deduction/salary-deduction.component.ts new file mode 100644 index 00000000..608ccea5 --- /dev/null +++ b/brewman/static/app/salary-deduction/salary-deduction.component.ts @@ -0,0 +1,7 @@ +import {SalaryDeductionController} from "./salary-deduction.controller"; + +export const SalaryDeductionComponent = { + templateUrl: '/app/salary-deduction/salary-deduction.html', + controller: SalaryDeductionController, + controllerAs: 'vm', +}; \ No newline at end of file diff --git a/brewman/static/app/salary-deduction/salary-deduction.controller.js b/brewman/static/app/salary-deduction/salary-deduction.controller.js deleted file mode 100644 index 5a2da503..00000000 --- a/brewman/static/app/salary-deduction/salary-deduction.controller.js +++ /dev/null @@ -1,177 +0,0 @@ -angular - .module('overlord') - .controller('SalaryDeductionController', SalaryDeductionController); -SalaryDeductionController.$inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'voucher', 'Employee', 'uibDateParser']; -function SalaryDeductionController($scope, $location, asDate, $modal, voucher, Employee, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.voucher = voucher; - - function getOldItem(ledgerID, items) { - for (var i = 0, l = items.length; i < l; i++) { - if (items[i].Journal.Ledger.LedgerID === ledgerID) { - return items[i]; - } - } - } - - function daysInMonthFunction(date) { - if (angular.isDate(date)) { - return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); - } - - var months = { - Jan: 1, - Feb: 2, - Mar: 3, - Apr: 4, - May: 5, - Jun: 6, - Jul: 7, - Aug: 8, - Sep: 9, - Oct: 10, - Nov: 11, - Dec: 12 - }; - if (!date.match(/^\d{2}-[\w]{3}-[\d]{4}$/g)) { - return; - } - var parts = date.split("-"); - return new Date(parseInt(parts[2], 10), months[parts[1]], 0).getDate(); - } - - function getEsi(grossSalary, daysWorked, daysInMonth) { - var limit = 15000, - employeeRate = 0.0175, - employerRate = 0.0475, - employee = (grossSalary > limit) ? 0 : Math.ceil(employeeRate * grossSalary * daysWorked / daysInMonth), - employer = (grossSalary > limit) ? 0 : Math.ceil(employerRate * grossSalary * daysWorked / daysInMonth); - return {ee: employee, er: employer, both: employee + employer}; - } - - function getPf(grossSalary, daysWorked, daysInMonth) { - var limit = 15000, - employeeRate = 0.12, - employerRate = 0.12 + 0.011 + 0.005 + 0.0001, - employee = (grossSalary > limit) ? 0 : Math.ceil(employeeRate * grossSalary * daysWorked / daysInMonth), - employer = (grossSalary > limit) ? 0 : Math.ceil(employerRate * grossSalary * daysWorked / daysInMonth); - return {ee: employee, er: employer, both: employee + employer}; - } - - $scope.add = function () { - var oldJournal = getOldItem($scope.employee.LedgerID, $scope.voucher.SalaryDeductions), - grossSalary = parseInt($scope.grossSalary, 10), - daysWorked = parseInt($scope.daysWorked, 10), - daysInMonth = daysInMonthFunction($scope.voucher.Date), - esi = getEsi(grossSalary, daysWorked, daysInMonth), - pf = getPf(grossSalary, daysWorked, daysInMonth); - - if (!angular.isUndefined(oldJournal)) { - $scope.toasts.push({Type: 'Danger', Message: 'Employee has already been added!'}); - } else { - $scope.voucher.SalaryDeductions.push({ - Journal: {Ledger: $scope.employee}, - GrossSalary: grossSalary, - DaysWorked: daysWorked, - EsiEmployee: esi.ee, - PfEmployee: pf.ee, - EsiEmployer: esi.er, - PfEmployer: pf.er - }); - } - delete $scope.employee; - delete $scope.grossSalary; - delete $scope.daysWorked; - $scope.foEmployee = true; - }; - - $scope.remove = function (deduction) { - var index = $scope.voucher.SalaryDeductions.indexOf(deduction); - $scope.voucher.SalaryDeductions.splice(index, 1); - }; - - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined($scope.perms)) { - return false; - } else if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Salary Deduction']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID !== $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.save = function () { - $scope.voucher.$save({type: 'Salary Deduction'}, function (u) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/SalaryDeduction/' + u.VoucherID); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.voucher.$delete(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/SalaryDeduction').replace(); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.post = function () { - $scope.voucher.$post(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; - - $scope.employees = function ($viewValue) { - return Employee.autocomplete({term: $viewValue, count: 20}).$promise; - }; -} - - -SalaryDeductionController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id; - - if (angular.isUndefined(id)) { - return Voucher.get({type: 'Salary Deduction'}).$promise; - } else { - return Voucher.get({id: id}).$promise; - } - }] -}; diff --git a/brewman/static/app/salary-deduction/salary-deduction.controller.ts b/brewman/static/app/salary-deduction/salary-deduction.controller.ts new file mode 100644 index 00000000..0589097b --- /dev/null +++ b/brewman/static/app/salary-deduction/salary-deduction.controller.ts @@ -0,0 +1,181 @@ +import * as angular from 'angular'; + +export class SalaryDeductionController { + static $inject = ['$scope', '$location', 'asDateFilter', '$uibModal', 'Employee', 'uibDateParser', 'Messages', 'Credentials']; + _voucher_Date: any; + employee: any; + grossSalary: any; + daysWorked: any; + foEmployee: any; + voucher: any; + + constructor(public $scope, public $location, public asDate, public $modal, public Employee, public dateParser, public Messages, public Credentials) { + this.voucher = $scope.$parent.res.voucher; + this._voucher_Date = dateParser.parse(this.voucher.Date, "dd-MMM-yyyy"); + } + + voucher_Date(value) { + if (arguments.length) { + this.voucher.Date = this.asDate(value); + this._voucher_Date = value; + } + return this._voucher_Date; + } + + getOldItem(ledgerID, items) { + for (let i = 0, l = items.length; i < l; i++) { + if (items[i].Journal.Ledger.LedgerID === ledgerID) { + return items[i]; + } + } + } + + daysInMonthFunction(date) { + if (angular.isDate(date)) { + return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); + } + + const months = { + Jan: 1, + Feb: 2, + Mar: 3, + Apr: 4, + May: 5, + Jun: 6, + Jul: 7, + Aug: 8, + Sep: 9, + Oct: 10, + Nov: 11, + Dec: 12 + }; + if (!date.match(/^\d{2}-[\w]{3}-[\d]{4}$/g)) { + return; + } + const parts = date.split("-"); + return new Date(parseInt(parts[2], 10), months[parts[1]], 0).getDate(); + } + + getEsi(grossSalary, daysWorked, daysInMonth) { + const limit = 15000, + employeeRate = 0.0175, + employerRate = 0.0475, + employee = (grossSalary > limit) ? 0 : Math.ceil(employeeRate * grossSalary * daysWorked / daysInMonth), + employer = (grossSalary > limit) ? 0 : Math.ceil(employerRate * grossSalary * daysWorked / daysInMonth); + return {ee: employee, er: employer, both: employee + employer}; + } + + getPf(grossSalary, daysWorked, daysInMonth) { + const limit = 15000, + employeeRate = 0.12, + employerRate = 0.12 + 0.011 + 0.005 + 0.0001, + employee = (grossSalary > limit) ? 0 : Math.ceil(employeeRate * grossSalary * daysWorked / daysInMonth), + employer = (grossSalary > limit) ? 0 : Math.ceil(employerRate * grossSalary * daysWorked / daysInMonth); + return {ee: employee, er: employer, both: employee + employer}; + } + + add() { + const oldJournal = this.getOldItem(this.employee.LedgerID, this.voucher.SalaryDeductions), + grossSalary = parseInt(this.grossSalary, 10), + daysWorked = parseInt(this.daysWorked, 10), + daysInMonth = this.daysInMonthFunction(this.voucher.Date), + esi = this.getEsi(grossSalary, daysWorked, daysInMonth), + pf = this.getPf(grossSalary, daysWorked, daysInMonth); + + if (!angular.isUndefined(oldJournal)) { + this.Messages.push({Type: 'Danger', Message: 'Employee has already been added!'}); + } else { + this.voucher.SalaryDeductions.push({ + Journal: {Ledger: this.employee}, + GrossSalary: grossSalary, + DaysWorked: daysWorked, + EsiEmployee: esi.ee, + PfEmployee: pf.ee, + EsiEmployer: esi.er, + PfEmployer: pf.er + }); + } + delete this.employee; + delete this.grossSalary; + delete this.daysWorked; + this.foEmployee = true; + } + + remove(deduction) { + const index = this.voucher.SalaryDeductions.indexOf(deduction); + this.voucher.SalaryDeductions.splice(index, 1); + } + + preventAlteration(voucher) { + if (angular.isUndefined(this.Credentials.Perms)) { + return false; + } else if (angular.isUndefined(voucher.VoucherID)) { + return !this.Credentials.Perms['Salary Deduction']; + } else if (voucher.Posted && !this.Credentials.Perms['Edit Posted Vouchers']) { + return true; + } else if (voucher.User.UserID !== this.Credentials.Auth.UserID && !this.Credentials.Perms["Edit Other User's Vouchers"]) { + return true; + } else { + return false; + } + } + + save() { + this.voucher.$save({type: 'Salary Deduction'}, (u) => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/SalaryDeduction/' + u.VoucherID); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.voucher.$delete(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/SalaryDeduction').replace(); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + post() { + this.voucher.$post((u, putResponseHeaders) => { + this.Messages.push({Type: 'Success', Message: ''}); + }, (data, status) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + confirm() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Delete Voucher"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.delete(); + }); + } + + employees($viewValue) { + return this.Employee.autocomplete({term: $viewValue, count: 20}).$promise; + } +} diff --git a/brewman/static/app/salary-deduction/salary-deduction.html b/brewman/static/app/salary-deduction/salary-deduction.html index 285e0246..b07d7e45 100644 --- a/brewman/static/app/salary-deduction/salary-deduction.html +++ b/brewman/static/app/salary-deduction/salary-deduction.html @@ -7,7 +7,7 @@
@@ -19,18 +19,18 @@
- +
- +
- +
-
@@ -50,7 +50,7 @@ - + {{deduction.Journal.Ledger.Name}} {{deduction.Journal.Ledger.Designation}} {{deduction.Journal.Ledger.CostCentre.Name}} @@ -61,7 +61,7 @@ {{deduction.EsiEmployer}} {{deduction.PfEmployer}} - @@ -71,18 +71,18 @@
- - -
- Created on {{voucher.CreationDate | localTime}} and Last Edited on {{voucher.LastEditDate | localTime}} by - {{voucher.User.Name}}. Posted by {{voucher.Poster}} + Created on {{vm.voucher.CreationDate | localTime}} and Last Edited on {{vm.voucher.LastEditDate | localTime}} by + {{vm.voucher.User.Name}}. Posted by {{vm.voucher.Poster}}
diff --git a/brewman/static/app/service-charge/service-charge.controller.js b/brewman/static/app/service-charge/service-charge.controller.js deleted file mode 100644 index 7cbb120e..00000000 --- a/brewman/static/app/service-charge/service-charge.controller.js +++ /dev/null @@ -1,123 +0,0 @@ -angular - .module('overlord') - .controller('ServiceChargeController', ServiceChargeController); -ServiceChargeController.$inject = ['$scope', '$location', '$routeParams', 'numberFilter', 'asDateFilter', '$uibModal', 'voucher', 'uibDateParser']; -function ServiceChargeController($scope, $location, $routeParams, numberFilter, asDate, $modal, voucher, dateParser) { - var _voucher_Date = dateParser.parse(voucher.Date, "dd-MMM-yyyy"); - $scope.voucher_Date = function (value) { - if (arguments.length) { - $scope.voucher.Date = asDate(value); - _voucher_Date = value; - } - return _voucher_Date; - }; - $scope.voucher = voucher; - - $scope.TotalPoints = function () { - return _($scope.voucher.ServiceCharges).map(function (item) { - return item.DaysWorked * Number(item.Points); - }).reduce(function (sum, item) { - return sum + item; - }); - }; - $scope.PointValue = function () { - return Math.round($scope.voucher.ServiceCharge * 100 / $scope.TotalPoints()) / 100; - }; - $scope.less = function (employee) { - if (employee.Points >= 1) { - employee.Points -= 1; - } - }; - $scope.more = function (employee) { - employee.Points += 1; - }; - - $scope.$watch('voucher.Date', function (newDate, oldDate) { - var nDate = asDate(newDate), - oDate = asDate(oldDate); - - - if (nDate !== oDate && !angular.isUndefined(nDate)) { - if (angular.isUndefined($routeParams.id)) { - return voucher.$get({type: 'Service Charge', Date: nDate}).$promise; - } - } - }, true); - - $scope.employeeAmount = function (employee) { - return Number(employee.Points) * employee.DaysWorked * $scope.PointValue(); - }; - $scope.preventAlteration = function (voucher) { - if (angular.isUndefined($scope.perms)) { - return false; - } else if (angular.isUndefined(voucher.VoucherID)) { - return !$scope.perms['Service Charge']; - } else if (voucher.Posted && !$scope.perms['Edit Posted Vouchers']) { - return true; - } else if (voucher.User.UserID !== $scope.auth.UserID && !$scope.perms["Edit Other User's Vouchers"]) { - return true; - } else { - return false; - } - }; - - $scope.save = function () { - $scope.voucher.$save({type: 'Service Charge'}, function (u) { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/ServiceCharge/' + u.VoucherID); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.voucher.$delete(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/ServiceCharge').replace(); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.post = function () { - $scope.voucher.$post(function (u, putResponseHeaders) { - $scope.toasts.push({Type: 'Success', Message: ''}); - }, function (data, status) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.confirm = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Delete Voucher"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.delete(); - }); - }; -} - - -ServiceChargeController.resolve = { - voucher: ['$route', 'Voucher', function ($route, Voucher) { - var id = $route.current.params.id; - - if (angular.isUndefined(id)) { - return Voucher.get({type: 'Service Charge'}).$promise; - } else { - return Voucher.get({id: id}).$promise; - } - }] -}; diff --git a/brewman/static/app/settings/lock-info.resolver.ts b/brewman/static/app/settings/lock-info.resolver.ts new file mode 100644 index 00000000..7b64b4ea --- /dev/null +++ b/brewman/static/app/settings/lock-info.resolver.ts @@ -0,0 +1,9 @@ +import * as angular from 'angular'; + +export class LockInfoResolver { + constructor(public $http) { + return $http.get('/api/LockInfo', {}).then(function (data) { + return data.data; + }); + } +} diff --git a/brewman/static/app/settings/maintenance.resolver.ts b/brewman/static/app/settings/maintenance.resolver.ts new file mode 100644 index 00000000..34a859c8 --- /dev/null +++ b/brewman/static/app/settings/maintenance.resolver.ts @@ -0,0 +1,9 @@ +import * as angular from 'angular'; + +export class MaintenanceResolver { + constructor(public $http) { + return $http.get('/api/Maintenance', {}).then(function (data) { + return data.data; + }); + } +} diff --git a/brewman/static/app/settings/settings.component.ts b/brewman/static/app/settings/settings.component.ts new file mode 100644 index 00000000..b5dad36f --- /dev/null +++ b/brewman/static/app/settings/settings.component.ts @@ -0,0 +1,7 @@ +import {SettingsController} from "./settings.controller"; + +export const SettingsComponent = { + templateUrl: '/app/settings/settings.html', + controller: SettingsController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/settings/settings.controller.js b/brewman/static/app/settings/settings.controller.js deleted file mode 100644 index 3f3fe87a..00000000 --- a/brewman/static/app/settings/settings.controller.js +++ /dev/null @@ -1,181 +0,0 @@ -angular - .module('overlord') - .controller('SettingsController', SettingsController); -SettingsController.$inject = ['$scope', '$http', 'asDateFilter', '$uibModal', 'lockInfo', 'maintenance', 'Product', 'uibDateParser']; -function SettingsController($scope, $http, asDate, $modal, lockInfo, maintenance, Product, dateParser) { - var _lockInfo_Start_Date, - _lockInfo_Finish_Date; - if (!angular.isUndefined(lockInfo.Start.Date)) { - _lockInfo_Start_Date = dateParser.parse(lockInfo.Start.Date, "dd-MMM-yyyy"); - } - if (!angular.isUndefined(lockInfo.Finish.Date)) { - _lockInfo_Finish_Date = dateParser.parse(lockInfo.Finish.Date, "dd-MMM-yyyy"); - } - $scope.lockInfo_Start_Date = function (value) { - if (arguments.length) { - $scope.lockInfo.Start.Date = asDate(value); - _lockInfo_Start_Date = value; - } - return _lockInfo_Start_Date; - }; - $scope.lockInfo_Finish_Date = function (value) { - if (arguments.length) { - $scope.lockInfo.Finish.Date = asDate(value); - _lockInfo_Finish_Date = value; - } - return _lockInfo_Finish_Date; - }; - - $scope.lockInfo = lockInfo; - $scope.maintenance = maintenance; - $scope.MaintenanceEnabled = function () { - return $scope.maintenance.Enabled ? 'Enabled' : 'Disabled'; - }; - $scope.rebaseDate = new Date(); - $scope.setLockDate = function () { - if ($scope.lockInfo.Start.Locked) { - if ($scope.lockInfo.Start.Rolling) { - $scope.lockInfo.Start.Days = parseInt($scope.lockInfo.Start.Days, 10); - } - } - - if ($scope.lockInfo.Finish.Locked) { - if ($scope.lockInfo.Finish.Rolling) { - $scope.lockInfo.Finish.Days = parseInt($scope.lockInfo.Finish.Days, 10); - } - } - return $http.post('/api/LockInfo', $scope.lockInfo). - then(function (data) { - $scope.lockInfo = data.data; - $scope.toasts.push({Type: 'Success', Message: ''}); - }). - catch(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage}); - }); - }; - - $scope.clearLockDate = function () { - return $http.delete('/api/LockInfo'). - then(function (data) { - $scope.lockInfo = data.data; - $scope.toasts.push({Type: 'Success', Message: ''}); - }). - catch(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage}); - }); - }; - - $scope.confirmRebase = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Rebase Data"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.rebaseData(); - }); - }; - $scope.rebaseData = function () { - if ($scope.rebaseDate === '') { - return; - } - $http({ - method: 'POST', url: '/api/Rebase/' + asDate($scope.rebaseDate) - }).then(function () { - $scope.toasts.push({Type: 'Success', Message: 'Data rebased!'}); - }).catch(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage}); - }); - }; - - $scope.confirmResetStock = function () { - var modalInstance = $modal.open({ - backdrop: true, - templateUrl: '/template/modal/confirm.html', - controller: ['$scope', '$uibModalInstance', function ($scope, $modalInstance) { - $scope.title = "Reset Stock"; - $scope.body = "Are you sure? This cannot be undone."; - $scope.isDelete = true; - $scope.ok = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - }] - }); - modalInstance.result.then(function () { - $scope.resetStock(); - }); - }; - $scope.resetStock = function () { - if (angular.isUndefined($scope.resetDate) || $scope.resetDate === '') { - return; - } - if (angular.isUndefined($scope.stockDate) || $scope.stockDate === '') { - return; - } - if (angular.isUndefined($scope.product) || $scope.product === '') { - return; - } - if (angular.isUndefined($scope.qty) || $scope.qty === '') { - return; - } - var qty = Number($scope.qty); - $http({ - method: 'POST', - url: '/api/ResetStock/' + $scope.product.ProductID, - params: {StockDate: asDate($scope.stockDate), ResetDate: asDate($scope.resetDate), Quantity: qty} - }).then(function () { - $scope.toasts.push({Type: 'Success', Message: 'Data rebased!'}); - }).catch(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage}); - }); - }; - $scope.products = function ($viewValue) { - return Product.autocomplete({term: $viewValue, count: 20}).$promise; - }; - - $scope.checkDb = function () { - return $http.post('/api/DbIntegrity', {}). - then(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - }).catch(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage}); - }); - }; - - $scope.setMaintenance = function (status) { - return $http.post('/api/Maintenance', {Enabled: status}). - then(function (data) { - $scope.maintenance = data; - $scope.toasts.push({Type: 'Success', Message: ''}); - }).catch(function (errorMessage) { - $scope.toasts.push({Type: 'Danger', Message: errorMessage}); - }); - }; -} - -SettingsController.resolve = { - lockInfo: ['$http', function ($http) { - return $http.get('/api/LockInfo', {}).then(function (data) { - return data.data; - }); - }], - maintenance: ['$http', function ($http) { - return $http.get('/api/Maintenance', {}).then(function (data) { - return data.data; - }); - }] -}; - diff --git a/brewman/static/app/settings/settings.controller.ts b/brewman/static/app/settings/settings.controller.ts new file mode 100644 index 00000000..2782ce49 --- /dev/null +++ b/brewman/static/app/settings/settings.controller.ts @@ -0,0 +1,194 @@ +import * as angular from 'angular'; + +export class SettingsController { + static $inject = ['$scope', '$http', 'asDateFilter', '$uibModal', 'Product', 'uibDateParser', 'Messages']; + _lockInfo_Start_Date: any; + _lockInfo_Finish_Date: any; + rebaseDate: any; + resetDate: any; + stockDate: any; + product: any; + qty: any; + lockInfo: any; + maintenance: any; + + constructor(public $scope, public $http, public asDate, public $modal, public Product, public dateParser, public Messages) { + this.lockInfo = $scope.$parent.res.lockInfo; + this.maintenance = $scope.$parent.res.maintenance; + this._lockInfo_Start_Date = undefined; + this._lockInfo_Finish_Date = undefined; + if (!angular.isUndefined(this.lockInfo.Start.Date)) { + this._lockInfo_Start_Date = dateParser.parse(this.lockInfo.Start.Date, "dd-MMM-yyyy"); + } + if (!angular.isUndefined(this.lockInfo.Finish.Date)) { + this._lockInfo_Finish_Date = dateParser.parse(this.lockInfo.Finish.Date, "dd-MMM-yyyy"); + } + this.rebaseDate = new Date(); + } + + lockInfo_Start_Date(value) { + if (arguments.length) { + this.lockInfo.Start.Date = this.asDate(value); + this._lockInfo_Start_Date = value; + } + return this._lockInfo_Start_Date; + } + + lockInfo_Finish_Date(value) { + if (arguments.length) { + this.lockInfo.Finish.Date = this.asDate(value); + this._lockInfo_Finish_Date = value; + } + return this._lockInfo_Finish_Date; + } + + MaintenanceEnabled() { + return this.maintenance.Enabled ? 'Enabled' : 'Disabled'; + } + + setLockDate() { + if (this.lockInfo.Start.Locked) { + if (this.lockInfo.Start.Rolling) { + this.lockInfo.Start.Days = parseInt(this.lockInfo.Start.Days, 10); + } + } + + if (this.lockInfo.Finish.Locked) { + if (this.lockInfo.Finish.Rolling) { + this.lockInfo.Finish.Days = parseInt(this.lockInfo.Finish.Days, 10); + } + } + return this.$http.post('/api/LockInfo', this.lockInfo).then((data) => { + this.lockInfo = data.data; + this.Messages.push({Type: 'Success', Message: ''}); + }).catch((errorMessage) => { + this.Messages.push({Type: 'Danger', Message: errorMessage}); + }); + } + + clearLockDate() { + return this.$http.delete('/api/LockInfo').then((data) => { + this.lockInfo = data.data; + this.Messages.push({Type: 'Success', Message: ''}); + }).catch((errorMessage) => { + this.Messages.push({Type: 'Danger', Message: errorMessage}); + }); + } + + confirmRebase() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Rebase Data"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.rebaseData(); + }); + } + + rebaseData() { + if (this.rebaseDate === '') { + return; + } + this.$http({ + method: 'POST', url: '/api/Rebase/' + this.asDate(this.rebaseDate) + }).then(() => { + this.Messages.push({Type: 'Success', Message: 'Data rebased!'}); + }).catch((errorMessage) => { + this.Messages.push({Type: 'Danger', Message: errorMessage}); + }); + } + + confirmResetStock() { + const modalInstance = this.$modal.open({ + backdrop: true, + templateUrl: '/template/modal/confirm.html', + controller: ['$uibModalInstance', class { + title: any; + body: any; + isDelete: boolean; + + constructor(public $modalInstance) { + this.title = "Reset Stock"; + this.body = "Are you sure? This cannot be undone."; + this.isDelete = true; + } + + ok() { + this.$modalInstance.close(); + } + + cancel() { + this.$modalInstance.dismiss('cancel'); + } + }] + }); + modalInstance.result.then(() => { + this.resetStock(); + }); + } + + resetStock() { + if (angular.isUndefined(this.resetDate) || this.resetDate === '') { + return; + } + if (angular.isUndefined(this.stockDate) || this.stockDate === '') { + return; + } + if (angular.isUndefined(this.product) || this.product === '') { + return; + } + if (angular.isUndefined(this.qty) || this.qty === '') { + return; + } + const qty = Number(this.qty); + this.$http({ + method: 'POST', + url: '/api/ResetStock/' + this.product.ProductID, + params: {StockDate: this.asDate(this.stockDate), ResetDate: this.asDate(this.resetDate), Quantity: qty} + }).then(() => { + this.Messages.push({Type: 'Success', Message: 'Data rebased!'}); + }).catch((errorMessage) => { + this.Messages.push({Type: 'Danger', Message: errorMessage}); + }); + } + + products($viewValue) { + return this.Product.autocomplete({term: $viewValue, count: 20}).$promise; + } + + checkDb() { + return this.$http.post('/api/DbIntegrity', {}).then(() => { + this.Messages.push({Type: 'Success', Message: ''}); + }).catch(function (errorMessage) { + this.Messages.push({Type: 'Danger', Message: errorMessage}); + }); + } + + setMaintenance(status) { + return this.$http.post('/api/Maintenance', {Enabled: status}).then((data) => { + this.maintenance = data; + this.Messages.push({Type: 'Success', Message: ''}); + }).catch((errorMessage) => { + this.Messages.push({Type: 'Danger', Message: errorMessage}); + }); + } +} diff --git a/brewman/static/app/settings/settings.html b/brewman/static/app/settings/settings.html index 353fdb85..683f5090 100644 --- a/brewman/static/app/settings/settings.html +++ b/brewman/static/app/settings/settings.html @@ -7,26 +7,26 @@
-
+
-
+
- +
-
+
- @@ -39,26 +39,26 @@
-
+
-
+
- +
-
+
- @@ -68,10 +68,10 @@
- +
- +
@@ -82,14 +82,14 @@
+ is-open="vm.rbOpen" ng-focus="vm.rbOpen = true" ng-model="vm.rebaseDate"/>
-
@@ -100,7 +100,7 @@
+ is-open="vm.rdOpen" ng-focus="vm.rdOpen = true" ng-model="vm.resetDate" placeholder="Reset date"/> @@ -109,7 +109,7 @@
+ is-open="vm.sdOpen" ng-focus="vm.sdOpen = true" ng-model="vm.stockDate"/> @@ -117,16 +117,16 @@
-
- +
-
@@ -134,7 +134,7 @@
-
@@ -142,15 +142,15 @@
-
-
- Maintenance mode is {{MaintenanceEnabled()}} by user {{maintenance.User}} + Maintenance mode is {{vm.MaintenanceEnabled()}} by user {{vm.maintenance.User}}
diff --git a/brewman/static/app/stock-movement/stock-movement.component.ts b/brewman/static/app/stock-movement/stock-movement.component.ts new file mode 100644 index 00000000..4cacb3ad --- /dev/null +++ b/brewman/static/app/stock-movement/stock-movement.component.ts @@ -0,0 +1,7 @@ +import {StockMovementController} from "./stock-movement.controller"; + +export const StockMovementComponent = { + templateUrl: '/app/stock-movement/stock-movement.html', + controller: StockMovementController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/stock-movement/stock-movement.controller.js b/brewman/static/app/stock-movement/stock-movement.controller.js deleted file mode 100644 index 4379927f..00000000 --- a/brewman/static/app/stock-movement/stock-movement.controller.js +++ /dev/null @@ -1,40 +0,0 @@ -angular - .module('overlord') - .controller('StockMovementController', StockMovementController); -StockMovementController.$inject = ['$scope', '$location', 'asDateFilter', 'stockMovement', 'uibDateParser']; -function StockMovementController($scope, $location, asDate, stockMovement, dateParser) { - var _info_StartDate = dateParser.parse(stockMovement.StartDate, "dd-MMM-yyyy"), - _info_FinishDate = dateParser.parse(stockMovement.FinishDate, "dd-MMM-yyyy"); - $scope.info_StartDate = function (value) { - if (arguments.length) { - $scope.info.StartDate = asDate(value); - _info_StartDate = value; - } - return _info_StartDate; - }; - $scope.info_FinishDate = function (value) { - if (arguments.length) { - $scope.info.FinishDate = asDate(value); - _info_FinishDate = value; - } - return _info_FinishDate; - }; - $scope.info = stockMovement; - $scope.show = function () { - $location.path('/StockMovement').search({StartDate: $scope.info.StartDate, FinishDate: $scope.info.FinishDate}); - }; - $scope.foDate = true; -} - -StockMovementController.resolve = { - stockMovement: ['$route', 'StockMovement', function ($route, StockMovement) { - var startDate = $route.current.params.StartDate, - finishDate = $route.current.params.FinishDate; - - if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { - return StockMovement.get({}).$promise; - } else { - return StockMovement.get({StartDate: startDate, FinishDate: finishDate}).$promise; - } - }] -}; \ No newline at end of file diff --git a/brewman/static/app/stock-movement/stock-movement.controller.ts b/brewman/static/app/stock-movement/stock-movement.controller.ts new file mode 100644 index 00000000..d535db96 --- /dev/null +++ b/brewman/static/app/stock-movement/stock-movement.controller.ts @@ -0,0 +1,39 @@ +export class StockMovementController { + static $inject = ['$scope', '$location', 'asDateFilter', 'stockMovement', 'uibDateParser']; + _info_StartDate: any; + _info_FinishDate: any; + info: any; + foDate: any; + stockMovement: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.stockMovement = $scope.$parent.res.stockMovement; + this._info_StartDate = dateParser.parse(this.stockMovement.StartDate, "dd-MMM-yyyy"); + this._info_FinishDate = dateParser.parse(this.stockMovement.FinishDate, "dd-MMM-yyyy"); + this.info = this.stockMovement; + this.foDate = true; + } + + info_StartDate(value) { + if (arguments.length) { + this.info.StartDate = this.asDate(value); + this._info_StartDate = value; + } + return this._info_StartDate; + } + + info_FinishDate(value) { + if (arguments.length) { + this.info.FinishDate = this.asDate(value); + this._info_FinishDate = value; + } + return this._info_FinishDate; + } + + show() { + this.$location.path('/StockMovement').search({ + StartDate: this.info.StartDate, + FinishDate: this.info.FinishDate + }); + } +} diff --git a/brewman/static/app/stock-movement/stock-movement.html b/brewman/static/app/stock-movement/stock-movement.html index 0dd062c8..e5c78098 100644 --- a/brewman/static/app/stock-movement/stock-movement.html +++ b/brewman/static/app/stock-movement/stock-movement.html @@ -7,7 +7,7 @@
@@ -17,7 +17,7 @@
@@ -25,7 +25,7 @@
- +
@@ -41,7 +41,7 @@ - + {{item.Group}} {{item.Name}} {{item.Opening | number:2}} diff --git a/brewman/static/app/stock-movement/stock-movement.resolver.ts b/brewman/static/app/stock-movement/stock-movement.resolver.ts new file mode 100644 index 00000000..0c132611 --- /dev/null +++ b/brewman/static/app/stock-movement/stock-movement.resolver.ts @@ -0,0 +1,12 @@ +import * as angular from 'angular'; + +export function StockMovementResolver($route, StockMovement) { + const startDate = $route.current.params.StartDate, + finishDate = $route.current.params.FinishDate; + + if (angular.isUndefined(startDate) || angular.isUndefined(finishDate)) { + return StockMovement.get({}).$promise; + } else { + return StockMovement.get({StartDate: startDate, FinishDate: finishDate}).$promise; + } +} diff --git a/brewman/static/app/stock-movement/stock-movement.service.ts b/brewman/static/app/stock-movement/stock-movement.service.ts new file mode 100644 index 00000000..54ea2d3b --- /dev/null +++ b/brewman/static/app/stock-movement/stock-movement.service.ts @@ -0,0 +1,3 @@ +export function StockMovement($resource) { + return $resource('/api/StockMovement'); +} diff --git a/brewman/static/app/trial-balance/trial-balance.component.ts b/brewman/static/app/trial-balance/trial-balance.component.ts new file mode 100644 index 00000000..8d7dc02e --- /dev/null +++ b/brewman/static/app/trial-balance/trial-balance.component.ts @@ -0,0 +1,7 @@ +import {TrialBalanceController} from "./trial-balance.controller"; + +export const TrialBalanceComponent = { + templateUrl: '/app/trial-balance/trial-balance.html', + controller: TrialBalanceController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/trial-balance/trial-balance.controller.js b/brewman/static/app/trial-balance/trial-balance.controller.js deleted file mode 100644 index b408b182..00000000 --- a/brewman/static/app/trial-balance/trial-balance.controller.js +++ /dev/null @@ -1,30 +0,0 @@ -angular - .module('overlord') - .controller('TrialBalanceController', TrialBalanceController); -TrialBalanceController.$inject = ['$scope', '$location', 'asDateFilter', 'trialBalance', 'uibDateParser']; -function TrialBalanceController($scope, $location, asDate, trialBalance, dateParser) { - var _info_Date = dateParser.parse(trialBalance.Date, "dd-MMM-yyyy"); - $scope.info_Date = function (value) { - if (arguments.length) { - $scope.info.Date = asDate(value); - _info_Date = value; - } - return _info_Date; - }; - $scope.info = trialBalance; - $scope.show = function () { - $location.path('/TrialBalance/' + $scope.info.Date); - }; - $scope.foDate = true; -} -TrialBalanceController.resolve = { - trialBalance: ['$route', 'TrialBalance', function ($route, TrialBalance) { - var date = $route.current.params.date; - - if (angular.isUndefined(date)) { - return TrialBalance.get({}).$promise; - } else { - return TrialBalance.get({date: date}).$promise; - } - }] -}; \ No newline at end of file diff --git a/brewman/static/app/trial-balance/trial-balance.controller.ts b/brewman/static/app/trial-balance/trial-balance.controller.ts new file mode 100644 index 00000000..4872936c --- /dev/null +++ b/brewman/static/app/trial-balance/trial-balance.controller.ts @@ -0,0 +1,26 @@ +export class TrialBalanceController { + $inject = ['$scope', '$location', 'asDateFilter', 'uibDateParser']; + info: any; + _info_Date: any; + foDate: boolean; + trialBalance: any; + + constructor(public $scope, public $location, public asDate, public dateParser) { + this.trialBalance = $scope.$parent.res.trialBalance; + this._info_Date = dateParser.parse(this.trialBalance.Date, "dd-MMM-yyyy"); + this.info = this.trialBalance; + this.foDate = true; + } + + info_Date(value) { + if (arguments.length) { + this.info.Date = this.asDate(value); + this._info_Date = value; + } + return this._info_Date; + } + + show() { + this.$location.path('/TrialBalance/' + this.info.Date); + } +} diff --git a/brewman/static/app/trial-balance/trial-balance.html b/brewman/static/app/trial-balance/trial-balance.html index 679976ec..6687e1a2 100644 --- a/brewman/static/app/trial-balance/trial-balance.html +++ b/brewman/static/app/trial-balance/trial-balance.html @@ -7,7 +7,7 @@
@@ -15,7 +15,7 @@
- +
@@ -28,7 +28,7 @@ - + diff --git a/brewman/static/app/trial-balance/trial-balance.resolver.ts b/brewman/static/app/trial-balance/trial-balance.resolver.ts new file mode 100644 index 00000000..c1c51d92 --- /dev/null +++ b/brewman/static/app/trial-balance/trial-balance.resolver.ts @@ -0,0 +1,11 @@ +import * as angular from 'angular'; + +export function TrialBalanceResolver($route, TrialBalance) { + const date = $route.current.params.date; + + if (angular.isUndefined(date)) { + return TrialBalance.get({}).$promise; + } else { + return TrialBalance.get({date: date}).$promise; + } +} diff --git a/brewman/static/app/trial-balance/trial-balance.service.ts b/brewman/static/app/trial-balance/trial-balance.service.ts new file mode 100644 index 00000000..8ae5b0be --- /dev/null +++ b/brewman/static/app/trial-balance/trial-balance.service.ts @@ -0,0 +1,3 @@ +export function TrialBalance($resource) { + return $resource('/api/TrialBalance/:date'); +} diff --git a/brewman/static/app/unposted/unposted.component.ts b/brewman/static/app/unposted/unposted.component.ts new file mode 100644 index 00000000..8986df34 --- /dev/null +++ b/brewman/static/app/unposted/unposted.component.ts @@ -0,0 +1,7 @@ +import {UnpostedController} from "./unposted.controller"; + +export const UnpostedComponent = { + templateUrl: '/app/unposted/unposted.html', + controller: UnpostedController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/unposted/unposted.controller.js b/brewman/static/app/unposted/unposted.controller.js deleted file mode 100644 index 1b4e7344..00000000 --- a/brewman/static/app/unposted/unposted.controller.js +++ /dev/null @@ -1,18 +0,0 @@ -angular - .module('overlord') - .controller('UnpostedController', UnpostedController); -UnpostedController.$inject = ['$scope', 'info', 'Unposted']; -function UnpostedController($scope, info, Unposted) { - $scope.info = info; - $scope.refresh = function () { - Unposted.query({}, function (result) { - $scope.info = result; - $scope.apply(); - }); - }; -} -UnpostedController.resolve = { - info: ['Unposted', function (Unposted) { - return Unposted.query({}).$promise; - }] -}; \ No newline at end of file diff --git a/brewman/static/app/unposted/unposted.controller.ts b/brewman/static/app/unposted/unposted.controller.ts new file mode 100644 index 00000000..876f999d --- /dev/null +++ b/brewman/static/app/unposted/unposted.controller.ts @@ -0,0 +1,14 @@ +export class UnpostedController { + $inject = ['$scope', 'Unposted']; + info: any; + + constructor(public $scope, public Unposted) { + this.info = $scope.$parent.res.info; + } + + refresh() { + this.Unposted.query({}, (result) => { + this.info = result; + }); + } +} diff --git a/brewman/static/app/unposted/unposted.html b/brewman/static/app/unposted/unposted.html index 325ab979..a6b70d67 100644 --- a/brewman/static/app/unposted/unposted.html +++ b/brewman/static/app/unposted/unposted.html @@ -1,5 +1,5 @@ -

Unposted Entries Refresh Unposted Entries Refresh

{{item.Type}} {{item.Name}} {{item.Debit | accounting}}
@@ -15,7 +15,7 @@ - + diff --git a/brewman/static/app/unposted/unposted.resolver.ts b/brewman/static/app/unposted/unposted.resolver.ts new file mode 100644 index 00000000..4f889c5b --- /dev/null +++ b/brewman/static/app/unposted/unposted.resolver.ts @@ -0,0 +1,6 @@ +import * as angular from 'angular'; + +export function UnpostedResolver(Unposted) { + return Unposted.query({}).$promise; +} + diff --git a/brewman/static/app/unposted/unposted.service.ts b/brewman/static/app/unposted/unposted.service.ts new file mode 100644 index 00000000..ab082d84 --- /dev/null +++ b/brewman/static/app/unposted/unposted.service.ts @@ -0,0 +1,3 @@ +export function Unposted($resource) { + return $resource('/api/Unposted'); +} diff --git a/brewman/static/app/user/user-detail.html b/brewman/static/app/user/user-detail.html index 37d543c9..5bad475d 100644 --- a/brewman/static/app/user/user-detail.html +++ b/brewman/static/app/user/user-detail.html @@ -5,7 +5,7 @@
- +
@@ -13,7 +13,7 @@
- +
@@ -21,7 +21,7 @@
@@ -30,17 +30,17 @@
-
+
- +
- +
diff --git a/brewman/static/app/user/user-list.component.ts b/brewman/static/app/user/user-list.component.ts new file mode 100644 index 00000000..764c0e11 --- /dev/null +++ b/brewman/static/app/user/user-list.component.ts @@ -0,0 +1,7 @@ +import {UserListController} from "./user-list.controller"; + +export const UserListComponent = { + templateUrl: '/app/user/user-list.html', + controller: UserListController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/user/user-list.controller.js b/brewman/static/app/user/user-list.controller.js deleted file mode 100644 index 5d26209f..00000000 --- a/brewman/static/app/user/user-list.controller.js +++ /dev/null @@ -1,13 +0,0 @@ -angular - .module('overlord') - .controller('UserListController', UserListController); -UserListController.$inject = ['$scope', 'users']; -function UserListController($scope, users) { - $scope.info = users; -} - -UserListController.resolve = { - users: ['User', function (User) { - return User.query({}).$promise; - }] -}; diff --git a/brewman/static/app/user/user-list.controller.ts b/brewman/static/app/user/user-list.controller.ts new file mode 100644 index 00000000..2d810a7b --- /dev/null +++ b/brewman/static/app/user/user-list.controller.ts @@ -0,0 +1,10 @@ +export class UserListController { + static $inject = ['$scope']; + info: any; + users:any; + + constructor(public $scope) { + this.users = $scope.$parent.res.users; + this.info = this.users; + } +} diff --git a/brewman/static/app/user/user-list.html b/brewman/static/app/user/user-list.html index 0aa83356..59f2f730 100644 --- a/brewman/static/app/user/user-list.html +++ b/brewman/static/app/user/user-list.html @@ -8,7 +8,7 @@
- +
{{item.Date}} {{item.Type}}
{{item.Name}} {{item.LockedOut}} diff --git a/brewman/static/app/user/user-list.resolver.ts b/brewman/static/app/user/user-list.resolver.ts new file mode 100644 index 00000000..5268037f --- /dev/null +++ b/brewman/static/app/user/user-list.resolver.ts @@ -0,0 +1,4 @@ +export function UserListResolver(User) { + return User.query({}).$promise; +} + diff --git a/brewman/static/app/user/user.component.ts b/brewman/static/app/user/user.component.ts new file mode 100644 index 00000000..6d0751b6 --- /dev/null +++ b/brewman/static/app/user/user.component.ts @@ -0,0 +1,7 @@ +import {UserController} from "./user.controller"; + +export const UserComponent = { + templateUrl: '/app/user/user-detail.html', + controller: UserController, + controllerAs: 'vm', +}; diff --git a/brewman/static/app/user/user.controller.js b/brewman/static/app/user/user.controller.js deleted file mode 100644 index 493dedef..00000000 --- a/brewman/static/app/user/user.controller.js +++ /dev/null @@ -1,33 +0,0 @@ -angular - .module('overlord') - .controller('UserController', UserController); -UserController.$inject = ['$scope', '$location', 'user']; -function UserController($scope, $location, user) { - $scope.user = user; - - $scope.save = function () { - $scope.user.$save(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Users'); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - - $scope.delete = function () { - $scope.user.$delete(function () { - $scope.toasts.push({Type: 'Success', Message: ''}); - $location.path('/Users'); - }, function (data) { - $scope.toasts.push({Type: 'Danger', Message: data.data}); - }); - }; - $scope.foName = true; -} - -UserController.resolve = { - user: ['$route', 'User', function ($route, User) { - var id = $route.current.params.id; - return User.get({id: id}).$promise; - }] -}; diff --git a/brewman/static/app/user/user.controller.ts b/brewman/static/app/user/user.controller.ts new file mode 100644 index 00000000..b9803988 --- /dev/null +++ b/brewman/static/app/user/user.controller.ts @@ -0,0 +1,28 @@ +export class UserController { + static $inject = ['$scope', '$location', 'Messages']; + foName: any; + user: any; + + constructor(public $scope, public $location, public Messages) { + this.user = $scope.$parent.res.user; + this.foName = true; + } + + save() { + this.user.$save(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Users'); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } + + delete() { + this.user.$delete(() => { + this.Messages.push({Type: 'Success', Message: ''}); + this.$location.path('/Users'); + }, (data) => { + this.Messages.push({Type: 'Danger', Message: data.data}); + }); + } +} diff --git a/brewman/static/app/user/user.resolver.ts b/brewman/static/app/user/user.resolver.ts new file mode 100644 index 00000000..326f9e43 --- /dev/null +++ b/brewman/static/app/user/user.resolver.ts @@ -0,0 +1,4 @@ +export function UserResolver($route, User) { + const id = $route.current.params.id; + return User.get({id: id}).$promise; +} diff --git a/brewman/static/app/user/user.service.ts b/brewman/static/app/user/user.service.ts new file mode 100644 index 00000000..f5cafb83 --- /dev/null +++ b/brewman/static/app/user/user.service.ts @@ -0,0 +1,7 @@ +export function User($resource) { + return $resource('/api/User/:id', + {id: '@UserID'}, { + query: {method: 'GET', params: {list: true}, isArray: true}, + names: {method: 'GET', params: {names: true}, isArray: true} + }); +} diff --git a/brewman/static/base.html b/brewman/static/base.html index d5348244..6d488a50 100644 --- a/brewman/static/base.html +++ b/brewman/static/base.html @@ -11,7 +11,6 @@ - @@ -26,93 +25,21 @@ } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + @@ -122,7 +49,7 @@ - +
-
+
{{toast.Type}}! {{toast.Message}}
diff --git a/brewman/static/js/jquery-2.1.3.min.js b/brewman/static/js/jquery-2.1.3.min.js deleted file mode 100644 index 25714ed2..00000000 --- a/brewman/static/js/jquery-2.1.3.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c) -},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("