First commit waiting for Budget Alert
This commit is contained in:
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
./init-db
|
||||||
54
.gitignore
vendored
Normal file
54
.gitignore
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Gradle
|
||||||
|
build
|
||||||
|
.gradle
|
||||||
|
|
||||||
|
# Eclispe
|
||||||
|
bin
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings
|
||||||
|
.metadata
|
||||||
|
|
||||||
|
# Intellij
|
||||||
|
out
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# NetBeans
|
||||||
|
.nbattrs
|
||||||
|
|
||||||
|
# virtual machine crash logs
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*.sw[nop]
|
||||||
|
*~
|
||||||
|
.#*
|
||||||
|
[#]*#
|
||||||
|
|
||||||
|
# dotenv or direnv
|
||||||
|
.env
|
||||||
|
.envrc
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
*.log
|
||||||
|
.clover
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Profiler and heap dumps
|
||||||
|
*.jps
|
||||||
|
*.hprof
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
# JavaScript
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
src/main/resources/application.properties
|
||||||
|
src/main/resources/application.properties
|
||||||
|
src/main/resources/application.properties
|
||||||
|
init-db/bdd_sophal202506281027.sql
|
||||||
|
modules/axelor-open-suite/axelor-account/src/test/resources/META-INF/persistence.xml
|
||||||
|
modules/axelor-open-suite/axelor-supplychain/src/test/java/com/axelor/apps/supplychain/db/StockMove.java
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "axelor-open-suite"]
|
||||||
|
path = modules/axelor-open-suite
|
||||||
|
url = git@github.com:axelor/axelor-open-suite.git
|
||||||
49
.vscode/launch.json
vendored
Normal file
49
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "Test",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "com.axelor.apps.account.service.Test",
|
||||||
|
"projectName": "axelor-account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "Previous",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "com.axelor.apps.production.service.Previous",
|
||||||
|
"projectName": "axelor-production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "AccountingCutOffServiceImpl",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "com.axelor.apps.supplychain.service.AccountingCutOffServiceImpl",
|
||||||
|
"projectName": "axelor-supplychain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "Test",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "com.axelor.apps.stock.service.Test",
|
||||||
|
"projectName": "axelor-stock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "Current File",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "${file}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "java",
|
||||||
|
"name": "QAPortType_QAPortType_Client",
|
||||||
|
"request": "launch",
|
||||||
|
"mainClass": "com.qas.web_2005_02.QAPortType_QAPortType_Client",
|
||||||
|
"projectName": "axelor-tool"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"java.compile.nullAnalysis.mode": "automatic",
|
||||||
|
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx8G -Xms100m -Xlog:disable",
|
||||||
|
"java.debug.settings.onBuildFailureProceed": true
|
||||||
|
}
|
||||||
265
CHANGELOG.md
Normal file
265
CHANGELOG.md
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [5.2.1] - 2019-12-16
|
||||||
|
## Features
|
||||||
|
- ACCOUNTING REPORT: add new report, bank reconciliation statement.
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
- INVOICE: new mandatory labelling: Head office address.
|
||||||
|
- Company: Add tree view for companies.
|
||||||
|
- AdvancedExportLine: Add translation for field orderByType.
|
||||||
|
- PURCHASE REQUEST: add new columns in purchase request grid view.
|
||||||
|
- MOVE: changed position of reconciliation tag in move form.
|
||||||
|
- BANK STATEMENT: add caption under bank statement line grid in bank statement form in order to explain the colors are used in bank statement line grid.
|
||||||
|
- PRODUCT: update translation for "Service" and "Product".
|
||||||
|
- STOCK MOVE: empty reservation date time on duplicate stock move.
|
||||||
|
- STOCK MOVE: Update stock move's form view.
|
||||||
|
- SALE ORDER PRINTING: rename title "Sale order" to "Order Acknowledgement" of report on condition.
|
||||||
|
- MOVE: Improved messages when there is an exception on trying to remove an accounting move.
|
||||||
|
- Partner Form: change the french translation of "Create sale quotation".
|
||||||
|
- STOCK MOVE: empty to and from stock location set on company change.
|
||||||
|
- STOCK MOVE: hide reserved qty when it is a supplier arrival or a customer return.
|
||||||
|
- STOCK MOVE: rename title of stock-move-form buttons related to PFP.
|
||||||
|
- STOCK MOVE: update pfp tags on stock move form.
|
||||||
|
- Invoicing project: unit conversion for "Duration adjust for customer".
|
||||||
|
- ACCOUNTING REPORT: change the title of "General ledger 2" from the selection.
|
||||||
|
- TAX: Show type select in grid view.
|
||||||
|
- Sale order/quotation: fix tab title when generating a quotation from an opportunity.
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
- ANALYTIC: analytic journal in analytic line is now required.
|
||||||
|
- REFUND: avoid blocking message when ventilating the invoice.
|
||||||
|
- MOVE: fix display of status tag in move form.
|
||||||
|
- Manuf Order: fix real quantity not updating when a new line in consumed products is created.
|
||||||
|
- INVOICE PAYMENT CANCELLATION: corrected error when boolean allow removal validate move in account configuration is true.
|
||||||
|
- INVOICE: stopped the creation of invoice payment when a reconciliation is made with accounts not used in partner balance.
|
||||||
|
- User: find user by email using partner email address.
|
||||||
|
- Invoice: fix exception during passed for payment validation.
|
||||||
|
- Resolve NPE on stockMoveLines while displaying archived records.
|
||||||
|
- StockMove: set readonly to/fromStockLocation if status != Draft.
|
||||||
|
- INVOICE: remove the possibility for the user to manually link a stockMove to an invoice.
|
||||||
|
- PURCHASE ORDER LINE: isFilterOnSupplier is always true by default and can be set to false manually.
|
||||||
|
- INVOICE: Fix error on merging two invoices.
|
||||||
|
- Invoice: fix payment button visibility issue.
|
||||||
|
- HR: update insert leave method for mobile app.
|
||||||
|
- INVOICE: Fix printing of unit price when invoiceLine type is title.
|
||||||
|
- MOVE LINE: fix amount paid display in move line form.
|
||||||
|
- STOCK: ProductWorth computation fixed in ABCAnalysis.
|
||||||
|
- BASE: ABC Analysis Line with qty and worth equal to 0 are now removed.
|
||||||
|
- Fix Issues on EBICS user and partner form.
|
||||||
|
- Purchase Order: fix view budgetDistributionListPanel of purchaseOrderLine.
|
||||||
|
- Weighted Average Price: Fix computation issue causing an error in wap price.
|
||||||
|
- STOCK MOVE: fix the problem of partially invoiced qty in invoicing wizard form.
|
||||||
|
- STOCK CORRECTION: fixed error when qty is negative by reversing toStockLocation and fromStockLocation of created stock move.
|
||||||
|
- MASS INVOICING STOCK MOVE: fix error when selecting stock move to invoice.
|
||||||
|
|
||||||
|
## [5.2.0] - 2019-11-29
|
||||||
|
## Features
|
||||||
|
- Migration to Axelor Open Platform 5.2.
|
||||||
|
- Axelor-Business-Support: Addition of new module and app 'axelor-business-support'.
|
||||||
|
- Employee: added DPAE.
|
||||||
|
- TeamTask: added Frequency to be able to repeat tasks on given points in time.
|
||||||
|
- Employee: added wizard to create a new employee.
|
||||||
|
- SaleOrder: added possibility to invoice via generated task.
|
||||||
|
- Project: add support for project version.
|
||||||
|
- Project: add new form to create announcement for a given project.
|
||||||
|
- New menu and form stock correction allowing to fix a quantity in stock.
|
||||||
|
- User Form: Provide step wise view to create a user.
|
||||||
|
- TeamTask: Complete rework of team task model and views.
|
||||||
|
- Project: Complete rework of project model and views.
|
||||||
|
- Base: Addition of new object 'MailingListMessage' along with views, parent menu and sub-menus.
|
||||||
|
- InvoicingProject: Added new report 'InvoicingProjectAnnex.rptdesign' and attach to object on generating invoice.
|
||||||
|
- HR: Add CSV export support for Employment Contracts from its view and HR batch.
|
||||||
|
- Quality: Major improvements in axelor-quality module.
|
||||||
|
- QUALITY CONTROL: New report to print.
|
||||||
|
- AppBase: Add new configuration allowing to disable multi company support.
|
||||||
|
- OPPORTUNITY: Create event from opportunity.
|
||||||
|
- PROJECT: Add new feature allowing to create a template for a project.
|
||||||
|
- Invoice & PurchaseOrder: Added a budget overview.
|
||||||
|
- Advanced Import: Add feature to import data with advanced configurations.
|
||||||
|
- BPM: More than one workflow support for a same object.
|
||||||
|
- Sale Order/Sale Invoice: allow to change customer in existing invoice or order.
|
||||||
|
- MESSAGE TEMPLATE: added the management of additional contexts (groovy evaluation) in order to allow the use of Json fields.
|
||||||
|
- FORECAST RECAP: Add support of printing report in 'xls' and 'ods' format.
|
||||||
|
- PERIOD: Add a new popup when closing period to allow user to check and validate move lines.
|
||||||
|
- Stock Move: Add support for partial invoicing.
|
||||||
|
- ABC ANALYSIS: Add support for printing report in 'xls' type.
|
||||||
|
- Business Project: Add 'Project invoicing assistant' batch to update tasks and generate invoicing projects.
|
||||||
|
- Project Folder: Add two printings to display all project elements linked to the folder.
|
||||||
|
- Distance travelled calculation of kilometric expense line with Open street map.
|
||||||
|
- Timesheet: add timesheet reporting.
|
||||||
|
- Stock: Add stock history view for a given product, company and stock location.
|
||||||
|
- Production: Provide menu for Machine Planning.
|
||||||
|
- Company: Add employee Phonebook.
|
||||||
|
- Base: Addition of fields 'height' and 'width' in Company to change logo's dimension in Reports.
|
||||||
|
- Add a payment validator in supplier invoices.
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
- SaleOrder/Partner: adding new fields for comments on invoices, sale orders, purchase orders and deliveries.
|
||||||
|
- Timesheet: assign Task to lines when generating from Realise Planning.
|
||||||
|
- Timesheet: mark timesheet line as to be invoiced while generating it from Realise Planning.
|
||||||
|
- TeamTask: Add button to enter spent time.
|
||||||
|
- LogisticalForm: if config enabled, send an email on first save.
|
||||||
|
- MANUF. APP: new config to hide cost sheet group.
|
||||||
|
- Purchase Request: Add the possibility to select purchase orders.
|
||||||
|
- Production: Addition of two dummy fields to calculate sum of planned and real duration of operation orders.
|
||||||
|
- MOVE: improve reversion process.
|
||||||
|
- SaleOrder: task by product and task by line invoicing.
|
||||||
|
- SALE ORDER: Update in 'Quotations template' working process and view.
|
||||||
|
- DataBackup: Add possibility to restore date fields from a given relative date.
|
||||||
|
- PURCHASE ORDER LINES/INVOICE LINES: New fields related to budget.
|
||||||
|
- WEEKLY PLANNING: Add a type and minor changes.
|
||||||
|
- BULK UNIT COST CALCULATION: new way to compute all unit costs using BOM. Allow to compute cost using BOM level sequence.
|
||||||
|
- MRP: Generate new sequence on save.
|
||||||
|
- DataBackup: update importId when its null with format IDDDMMYYHHMM.
|
||||||
|
- Generating supplier order from partner form.
|
||||||
|
- Mobile App: Add configuration for quality app on mobile app.
|
||||||
|
- INVOICE: new process to print.
|
||||||
|
- PERMISSIONS: Display dashlets for groups/roles/users using the permission in permission and meta permission form views.
|
||||||
|
- OPPORTUNITY: Rename "opportunity type" to "type of need".
|
||||||
|
- INVOICE: Change form view's organization to match the SaleOrder view.
|
||||||
|
- PARTNER: Add link to employee form.
|
||||||
|
- PRICE LIST: Add dashlets to display partner.
|
||||||
|
- MRP: add boolean to exclude product without proposal in the result dashlet.
|
||||||
|
- HR: TRAINING - Optimization of the menu by adding filters
|
||||||
|
- MRP: Group proposals per supplier
|
||||||
|
- HR: rework training and recruitment menus.
|
||||||
|
- Data import: in the import file, add the possibility to fill selects either by values, title or translated titles.
|
||||||
|
- Action Builder: Add feature to create templates using json models to send email.
|
||||||
|
- FORECAST RECAP: sequence feature added for ForeCastRecap.
|
||||||
|
- Advance data import: Add new config to check if new configuration is added on file and do import according to file.
|
||||||
|
- UNIT: allows to translate name and label.
|
||||||
|
- STOCK RULE: Add template on StockRule and StockConfig used for mail notifications.
|
||||||
|
- CONFORMITY CERTIFICATE: display external reference on printing.
|
||||||
|
- TIMESHEET: new config to display line numbers.
|
||||||
|
- Advanced Import: Add support of imported records removal.
|
||||||
|
- SALE ORDER: Recompute unit price when hideDiscount is true.
|
||||||
|
- OPPORTUNITY: Auto fill sale-order form and cancel linked sale orders on 'closed lost' status.
|
||||||
|
- OBJECT DATA CONFIG: UX improvements and translations and change in export type.
|
||||||
|
- ANALYTIC MOVE LINE: project field title changed and domain filter added.
|
||||||
|
- CONTRACT: Set invoice date with newly added options for invoicing moment.
|
||||||
|
- Inventory: Manage different type of inventory: yearly or cycle turning.
|
||||||
|
- Address: Street have now a dedicated object.
|
||||||
|
- SALE ORDER / PURCHASE ORDER / INVOICES: Lines panel height set to 30.
|
||||||
|
- MOVE: add the possibility to choose a date while generating reverse move.
|
||||||
|
- Contract: Add analytic information to contract lines.
|
||||||
|
- MESSAGE TEMPLATE: help to suggest use of separator between email addresses.
|
||||||
|
- PRODUCTION ORDER: user can define manuf order's planned end date while creating production order from product form.
|
||||||
|
- PARTNER: new HTML field on partner for proforma.
|
||||||
|
- Contract: added button to manually close contract if termination date was set in the future.
|
||||||
|
- ContractLine: hide `isConsumptionLine` if not activated in Contract config.
|
||||||
|
- Employee: Add a creation workflow and allow to automatically create or link a user.
|
||||||
|
- TimesheetLine: Add reference to TeamTask and add time to charge field.
|
||||||
|
- Timesheet: Change tab title.
|
||||||
|
- Studio: Allowing to export all data without selecting any app builder.
|
||||||
|
- Studio: Custom model editor - Added title property for model and removed required condition for AppBuilder.
|
||||||
|
- MENUS: new organisation in CRM and Sales modules.
|
||||||
|
- Mobile: Add new app setting for 'Task'.
|
||||||
|
- JobPosition: Cannot open a position when status in on hold.
|
||||||
|
- Purchase Order: remove IPurchaseOrder deprecated class.
|
||||||
|
- Event: Allowing to suppress unsynchronized events.
|
||||||
|
- Employee: Add birth department and city of birth in employee.
|
||||||
|
- Employment Contract: Set form width to large.
|
||||||
|
- Contract: partner/project filters improved.
|
||||||
|
- APP BUILDER: Remove JsonCreator object.
|
||||||
|
- ContractBatch: Set default bankDetails of partner to created invoice bankDetails.
|
||||||
|
- PRICE LIST: hide historized price lists in pop-up view.
|
||||||
|
- MARKETING: Precise domain for model in message template.
|
||||||
|
- Change titles for productFamily.
|
||||||
|
- CONTRACT: Set project on generated invoices.
|
||||||
|
- ACCOUNT MOVE REVERSE: Selected reverse move date must not be after the date of the day
|
||||||
|
- ACCOUNT MOVE REVERSE: add the possibility to choose to hide or not the move lines (origin and reverse) in bank reconciliation
|
||||||
|
- Change google-plus icon by google one.
|
||||||
|
- Sale Order Line: Replacing 'price' with 'priceDiscounted' in a Grid View along with PurchaseOrderLine and InvoiceLine
|
||||||
|
- SUPPLY CHAIN: delete boolean manageInvoicedAmountByLine.
|
||||||
|
- FUNCTION: new object function on Sales and CRM and new M2O on partner
|
||||||
|
- CITIZENSHIP: Add new object citizenship on base and new M2O in country and employee
|
||||||
|
- EMPLOYEE: Files management added domains and demo data
|
||||||
|
- Inventory: Added calendar-view
|
||||||
|
- change term "Description" to "Comment" in english and "Commentaire" in french
|
||||||
|
- WEEKLY PLANNING: Days can be reordered and created.
|
||||||
|
- PROJECT / REPORTINGS: Addition of new dashboard - "Planned charge".
|
||||||
|
- INVENTORY: adding ODS file format in report selection type.
|
||||||
|
- Quality Control: Set default printing setting and update translation.
|
||||||
|
- INVOICE: Configure BIRT to generate an Excel and a Word file
|
||||||
|
- KEYWORD: remove Keyword model.
|
||||||
|
- Advanced Import: trim data before import.
|
||||||
|
- ACCOUNTING: year and accountSet fields are set empty when company is changed.
|
||||||
|
- ACCOUNTING CONFIGURATION AND REPORTED BALANCE: add a new journal parameter in accounting configuration named reported balance journal and this new parameter defines the journal used in the reported balance move line creation.
|
||||||
|
- PARTNER: Checks the consistency of the address list of a partner.
|
||||||
|
- EXCEPTION: Removing deprecated interface IException.
|
||||||
|
- PORTAL CLIENT: Add config to choose the type of connection (from ABS or external).
|
||||||
|
- DEMO DATA: Rename field data.
|
||||||
|
- ACCOUNTING BATCH: alert when the closing annual accounts batch already ran.
|
||||||
|
- CLIENT PORTAL: update the client form view.
|
||||||
|
- USER: Mass generation of random passwords.
|
||||||
|
- Advance data import: Set sequence of filetab and removed temporary file at the end which is created during the process.
|
||||||
|
- ACCOUNTING REPORT: add ODS file formate in report export type.
|
||||||
|
- FORECAST RECAP: reset fields while creating duplicate record.
|
||||||
|
- PICKING ORDER: new comment field for picking order on partner.
|
||||||
|
- INVOICE: Add field 'language' to change report language in company.
|
||||||
|
- QUALITY CONTROL: Add send email option when status is finished.
|
||||||
|
- EMPLOYEE: add emergency contact relationship.
|
||||||
|
- INVOICE PAYMENT: additionnal informations
|
||||||
|
- ACCOUNT CONFIG: update demo data for account config and 'is print invoices in company language' boolean is now at true by default.
|
||||||
|
- Contract: change filter on project field.
|
||||||
|
- TEAMTASKS: Creation from Same Order.
|
||||||
|
- PROJECT: show sub-menu project list when project type is empty.
|
||||||
|
- Financial Report: calculate total costs (per line) in chart and totals.
|
||||||
|
- ACCOUNTING REPORT: add Analytic general ledger.
|
||||||
|
- TIMETABLE: reworked timetables to have them work based on percentage of the order rather than on a per product basis. So far only for sale orders. Purchases to come.
|
||||||
|
- HRconfig: moved fields 'Health service' and 'Health service address' to HR module.
|
||||||
|
- STOCKMOVE: update stock move form view.
|
||||||
|
- MetaScheduler: fix MetaScheduler form-view in axelor-base module.
|
||||||
|
- AccountingReport: set configuration to display opening accounting moves default value to true.
|
||||||
|
- SUPPLYCHAIN: auto-complete sale order when it has been completely invoiced.
|
||||||
|
- Accounting situation: added two fields to manage the credit insurance.
|
||||||
|
- BoM: added a menu showing personalized bills of materials.
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
- Studio: Fix import app without image.
|
||||||
|
- Generation of Project/Phase from SaleOrder.
|
||||||
|
- Contract: Fix issue of not saving currentContractVersion fields in form view.
|
||||||
|
- ProductTaskTemplate: fix button display issue for edit and remove buttons on tree view.
|
||||||
|
- Employee: Fix issue of not saving each phase of creation process.
|
||||||
|
- Marketing: Fix error when trying to generate an event per target.
|
||||||
|
- Contract: Fix import error in data-init.
|
||||||
|
- BUSINESS PROJECT: Report printing Division by zero.
|
||||||
|
- UnitCostCalculation: Fixed the date format in the csv export name file.
|
||||||
|
- BONUS MGT: Fix formula variable error of human resource when computing amounts.
|
||||||
|
- INVOICE: Hide Due amount in report while printing "Original invoice / Updated copy".
|
||||||
|
- PurchaseOrder: Fill order date with sale order creation date when generating puchase order from sale order with interco.
|
||||||
|
- Purchase Order: Rename field 'priceDisplay' to 'displayPriceOnQuotationRequest'.
|
||||||
|
- INVOICE: Reduce font size of tax table in Invoice printing.
|
||||||
|
- PURCHASE ORDER PRINTING: display buyer email and phone as in sale order printing.
|
||||||
|
- ACCOUNT MOVE REVERSE: add translation.
|
||||||
|
- Transactionnal: correction and standardisation of rollback.
|
||||||
|
- CONFIGURATOR BOM: product, qty and unit are displayed in the grid-view.
|
||||||
|
- SALE ORDER LINE: fixed error when selecting a product.
|
||||||
|
- Studio: Fix readonly fields are enabled when imported an application.
|
||||||
|
- Studio: Fix error when click on wkf buttons.
|
||||||
|
- Studio: Fix export app.
|
||||||
|
- Advance Data Import: Fix indexOutOfBound Exception.
|
||||||
|
- Advanced Data Import: Specify truncated value to sampleLines for large string.
|
||||||
|
- REPORTED BALANCE: corrected abnormal amount in reported balance move lines if there was no partner associated to it.
|
||||||
|
- REPORTED BALANCE BATCH: the case where reported balance date on fiscal year is missing is now correctly managed.
|
||||||
|
- PURCHASE ORDER: fix issue in 'discountTypeSelect' of Purchase Order Line Form.
|
||||||
|
- Advanced Data import: fix issue of not generating info in log file when error occurred on import.
|
||||||
|
- Studio: fix m2o to metafile's widget property, display image,binarylink option.
|
||||||
|
- Advance data import: fix search issue, changed default import type of relational field to New and add import if condition for required Fields.
|
||||||
|
- Advance data import: Fix Data import error when there is same object in two different sheets.
|
||||||
|
- INVOICE: fix issue of invoice copy.
|
||||||
|
- TEAMTASK: Add fullname in demo data.
|
||||||
|
- Timesheet line: Duration label issue when created from mobile app.
|
||||||
|
- Purchase: Corrected translation of purchase not configured.
|
||||||
|
- SALEORDERLINE: Issue when Production module isn't installed.
|
||||||
|
- Invoice: replace field "irrecoverablestatusSelect" to "irrecoverableStatusSelect".
|
||||||
|
- SALE ORDER: fix error generating project without salemanUser.
|
||||||
|
- Advance Import: Resolve ArrayIndexOutOfBound exception.
|
||||||
|
- STOCK: Link back order with saleOrder or purchaseOrder.
|
||||||
|
- ADDRESS: when there is one address on partner it is treated as a default address.
|
||||||
|
- LEAVE REQUEST: Add error when leave reason has no unit.
|
||||||
|
- LEAVE REQUEST: Set duration value 0 if day planning of selected weekly planning is empty
|
||||||
|
|
||||||
|
[5.2.1]: https://github.com/axelor/axelor-open-suite/compare/v5.2.0...v5.2.1
|
||||||
|
[5.2.0]: https://github.com/axelor/axelor-open-suite/compare/v5.1.13...v5.2.0
|
||||||
95
CONTRIBUTING.md
Normal file
95
CONTRIBUTING.md
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# Contributing Guide
|
||||||
|
|
||||||
|
We’d love for you to contribute to our source code and to make app even better.
|
||||||
|
While we try to keep requirements for contributing to a minimum,
|
||||||
|
there are a few guidelines we’d like you to follow:
|
||||||
|
|
||||||
|
* [Contributor License Agreement](#contributor-license-agreement)
|
||||||
|
* [Reporting Issues](#reporting-issues)
|
||||||
|
* [Submitting](#submitting)
|
||||||
|
* [Code of Conduct](#code-of-conduct)
|
||||||
|
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
By submitting code as an individual you agree to the [individual contributor license agreement][individual-cla].
|
||||||
|
By submitting code as an entity you agree to the [corporate contributor license agreement][corporate-cla].
|
||||||
|
|
||||||
|
## Reporting Issues
|
||||||
|
|
||||||
|
Before you submit your issue search the archive, maybe your question was already answered.
|
||||||
|
|
||||||
|
If your issue appears to be a bug, and hasn't been reported, open a new issue.
|
||||||
|
Help us to maximize the effort we can spend fixing issues and adding new features,
|
||||||
|
by not reporting duplicate issues. Providing the following information will increase
|
||||||
|
the chances of your issue being dealt with quickly:
|
||||||
|
|
||||||
|
* **Use Case** – explain your use case
|
||||||
|
* **Overview of the issue** – include stacktrace
|
||||||
|
* **Version** – which version you are using?
|
||||||
|
* **Browsers and Operating System** – is this a problem with all browsers?
|
||||||
|
* **Reproduce the Error** – provide a patch against app to reproduce the error
|
||||||
|
* **Related Issues** – has a similar issue been reported before?
|
||||||
|
* **Suggest a Fix** – you can point to what might be causing the problem (line of code or commit)
|
||||||
|
|
||||||
|
Please make sure you don’t post any sensitive information while reporting issues.
|
||||||
|
|
||||||
|
## Submitting
|
||||||
|
|
||||||
|
* [Fork](https://help.github.com/articles/fork-a-repo/) the repo.
|
||||||
|
* Code!
|
||||||
|
* Push your changes to the topic branch in your fork of the repository.
|
||||||
|
* Initiate a [pull request](http://help.github.com/send-pull-requests/)
|
||||||
|
* Update the issue, adding a comment including a link to the created pull request
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
As contributors and maintainers of this project, and in the interest of
|
||||||
|
fostering an open and welcoming community, we pledge to respect all people who
|
||||||
|
contribute through reporting issues, posting feature requests, updating
|
||||||
|
documentation, submitting pull requests or patches, and other activities.
|
||||||
|
|
||||||
|
We are committed to making participation in this project a harassment-free
|
||||||
|
experience for everyone, regardless of level of experience, gender, gender
|
||||||
|
identity and expression, sexual orientation, disability, personal appearance,
|
||||||
|
body size, race, ethnicity, age, religion, or nationality.
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery
|
||||||
|
* Personal attacks
|
||||||
|
* Trolling or insulting/derogatory comments
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing other's private information, such as physical or electronic
|
||||||
|
addresses, without explicit permission
|
||||||
|
* Other unethical or unprofessional conduct
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
By adopting this Code of Conduct, project maintainers commit themselves to
|
||||||
|
fairly and consistently applying these principles to every aspect of managing
|
||||||
|
this project. Project maintainers who do not follow or enforce the Code of
|
||||||
|
Conduct may be permanently removed from the project team.
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
|
when an individual is representing the project or its community.
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting a project maintainer at [conduct@axelor.com][mail]. All
|
||||||
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
|
is deemed necessary and appropriate to the circumstances. Maintainers are
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an
|
||||||
|
incident.
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 1.3.0, available at
|
||||||
|
[http://contributor-covenant.org/version/1/3/0/][version]
|
||||||
|
|
||||||
|
[mail]: mailto:conduct@axelor.com
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/3/0/
|
||||||
|
[individual-cla]: http://axelor.com/cla/individuel-cla/
|
||||||
|
[corporate-cla]: http://axelor.com/cla/corporate-cla/
|
||||||
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
FROM openjdk:8-jdk-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dos2unix for line-ending fixes
|
||||||
|
RUN apk add --no-cache bash dos2unix
|
||||||
|
|
||||||
|
# Copy everything
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Fix line endings for gradlew
|
||||||
|
RUN dos2unix ./gradlew && chmod +x ./gradlew
|
||||||
|
|
||||||
|
# Clean and run the Gradle app
|
||||||
|
CMD ["./gradlew", "clean", "run", "--no-daemon"]
|
||||||
|
|
||||||
|
|
||||||
669
LICENSE
Normal file
669
LICENSE
Normal file
@ -0,0 +1,669 @@
|
|||||||
|
Axelor is published under the GNU AFFERO GENERAL PUBLIC LICENSE, Version 3
|
||||||
|
(AGPLv3), as included below. Some external libraries and contributions bundled
|
||||||
|
with Axelor may be published under other AGPLv3-compatible licenses. For
|
||||||
|
these, please refer to the relevant source files and/or license files, in the
|
||||||
|
source code tree.
|
||||||
|
|
||||||
|
**************************************************************************
|
||||||
|
|
||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
180
PyWhatKit_DB.txt
Normal file
180
PyWhatKit_DB.txt
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
Date: 21/6/2024
|
||||||
|
Time: 19:13
|
||||||
|
Phone Number: +213554130569
|
||||||
|
Message: hello
|
||||||
|
--------------------
|
||||||
|
Date: 22/6/2024
|
||||||
|
Time: 21:33
|
||||||
|
Phone Number: +213554130569
|
||||||
|
Message: hello
|
||||||
|
--------------------
|
||||||
|
Date: 22/6/2024
|
||||||
|
Time: 21:36
|
||||||
|
Phone Number: +213542291107
|
||||||
|
Message: hello
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 0:8
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TEST MESSAGE
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 0:10
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TEST MESSAGE
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 0:16
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 0:19
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete acceptéhttp://localhost:8080/axelor-erp/#/ds/action-meta-actions/edit/3815
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 0:20
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté http://localhost:8080/axelor-erp/#/ds/action-meta-actions/edit/3815
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 0:21
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté http://localhost:8080/axelor-erp/#/ds/action-meta-actions/edit/3815
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 0:25
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté http://localhost:8080/axelor-erp/#/ds/action-meta-actions/edit/23400
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 11:53
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: hello https://dsi.sophal.dz//front/drh.MonDossierRH.php
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 11:54
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté http://localhost:8080/axelor-erp/#/ds/action-meta-actions/edit/22874
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 11:56
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/22874
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 12:0
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/22873
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 12:1
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/21515
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 12:1
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/21515
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 12:1
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/21515
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 12:1
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/20428
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 12:2
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/21515
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 12:2
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/21514
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 13:27
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: 40
|
||||||
|
--------------------
|
||||||
|
Date: 7/7/2024
|
||||||
|
Time: 13:31
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: 52
|
||||||
|
--------------------
|
||||||
|
Date: 8/7/2024
|
||||||
|
Time: 13:12
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/22026 sc.root.purchase.orders.supplier.lines.requests/edit 22026
|
||||||
|
--------------------
|
||||||
|
Date: 8/7/2024
|
||||||
|
Time: 13:13
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/22027 sc.root.purchase.orders.supplier.lines.requests/edit 22027
|
||||||
|
--------------------
|
||||||
|
Date: 8/7/2024
|
||||||
|
Time: 13:23
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/22026 sc.root.purchase.orders.supplier.lines.requests/edit 22026
|
||||||
|
--------------------
|
||||||
|
Date: 8/7/2024
|
||||||
|
Time: 13:26
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/22024 sc.root.purchase.orders.supplier.lines.requests/edit 22024
|
||||||
|
--------------------
|
||||||
|
Date: 8/7/2024
|
||||||
|
Time: 13:31
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: Votre TCO a ete accepté https://erp.sophal.net/sophal/#/ds/action-meta-actions/edit/23777 23777
|
||||||
|
--------------------
|
||||||
|
Date: 28/7/2024
|
||||||
|
Time: 11:30
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TEST MESSAGE sc.root.purchase.quotations/edit 22877
|
||||||
|
--------------------
|
||||||
|
Date: 28/7/2024
|
||||||
|
Time: 11:33
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TEST MESSAGE sc.root.purchase.quotations/edit 22878
|
||||||
|
--------------------
|
||||||
|
Date: 5/10/2024
|
||||||
|
Time: 22:53
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: msg 123
|
||||||
|
--------------------
|
||||||
|
Date: 5/10/2024
|
||||||
|
Time: 23:5
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TCO ACCEPTER sc.root.purchase.orders.supplier.lines.requests/edit 25759
|
||||||
|
--------------------
|
||||||
|
Date: 5/10/2024
|
||||||
|
Time: 23:15
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TCO ACCEPTER http://localhost:8080/axelor-erp/#/ds/sc.root.purchase.orders.supplier.lines.requests/edit 25759
|
||||||
|
--------------------
|
||||||
|
Date: 5/10/2024
|
||||||
|
Time: 23:23
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TCO ACCEPTER [go to](http://localhost:8080/axelor-erp/#/ds/sc.root.purchase.orders.supplier.lines.requests/edit) 25759
|
||||||
|
--------------------
|
||||||
|
Date: 5/10/2024
|
||||||
|
Time: 23:25
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TCO ACCEPTER [go to](https://erp.sophal.net/#/ds/sc.root.purchase.orders.supplier.lines.requests/edit) 25759
|
||||||
|
--------------------
|
||||||
|
Date: 5/10/2024
|
||||||
|
Time: 23:27
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TCO ACCEPTER https://erp.sophal.net/#/ds/sc.root.purchase.orders.supplier.lines.requests/edit25759 25759
|
||||||
|
--------------------
|
||||||
|
Date: 5/10/2024
|
||||||
|
Time: 23:27
|
||||||
|
Phone Number: +213541229487
|
||||||
|
Message: TCO ACCEPTER https://erp.sophal.net/#/ds/sc.root.purchase.orders.supplier.lines.requests/edit/25759 25759
|
||||||
|
--------------------
|
||||||
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Axelor Open Suite
|
||||||
|
================================
|
||||||
|
|
||||||
|
Axelor Open Suite reduces the complexity and improve responsiveness of business processes. Thanks to its modularity, you can start with few features and then activate other modules when needed.
|
||||||
|
|
||||||
|
Axelor Open Suite includes the following modules :
|
||||||
|
|
||||||
|
* Customer Relationship Management
|
||||||
|
* Sales management
|
||||||
|
* Financial and cost management
|
||||||
|
* Human Resource Management
|
||||||
|
* Project Management
|
||||||
|
* Inventory and Supply Chain Management
|
||||||
|
* Production Management
|
||||||
|
* Multi-company, multi-currency and multi-lingual
|
||||||
|
|
||||||
|
Axelor Open Suite is built on top of [Axelor Open Platform](https://github.com/axelor/axelor-open-platform)
|
||||||
|
|
||||||
|
Download
|
||||||
|
-------------------------
|
||||||
|
```bash
|
||||||
|
$ git clone git@github.com:axelor/open-suite-webapp.git
|
||||||
|
$ cd open-suite-webapp
|
||||||
|
$ git checkout master
|
||||||
|
$ git submodule init
|
||||||
|
$ git submodule update
|
||||||
|
$ git submodule foreach git checkout master
|
||||||
|
$ git submodule foreach git pull origin master
|
||||||
|
```
|
||||||
109
build.gradle
Normal file
109
build.gradle
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
buildscript {
|
||||||
|
ext.repos = {
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url 'https://plugins.gradle.org/m2/'
|
||||||
|
metadataSources {
|
||||||
|
artifact()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://repository.axelor.com/nexus/public/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ext.openPlatformVersion = '5.2.2'
|
||||||
|
ext.appVersion = '5.2.1'
|
||||||
|
repositories repos
|
||||||
|
dependencies {
|
||||||
|
classpath "com.axelor:axelor-gradle:${openPlatformVersion}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects { repositories repos }
|
||||||
|
|
||||||
|
apply plugin: 'idea'
|
||||||
|
apply plugin: 'eclipse'
|
||||||
|
apply plugin: "com.axelor.app"
|
||||||
|
|
||||||
|
apply from: './gradle/style.gradle'
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
runtime.exclude group:"org.eclipse.birt.runtime.3_7_1", module:"org.apache.commons.codec"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'idea'
|
||||||
|
apply plugin: 'eclipse'
|
||||||
|
|
||||||
|
group = "com.axelor"
|
||||||
|
version = "${appVersion}"
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
group = "com.axelor.apps"
|
||||||
|
}
|
||||||
|
|
||||||
|
axelor {
|
||||||
|
title "Sophal"
|
||||||
|
description "Sophal Entreprise"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
gradle.appModules.each { dir ->
|
||||||
|
compile project(":modules:$dir.name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper {
|
||||||
|
gradleVersion = "4.5.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
task("dataImport", type: JavaExec) {
|
||||||
|
main = "com.axelor.apps.erp.Main"
|
||||||
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
|
if(System.getProperty("exec.args") != null) {
|
||||||
|
args System.getProperty("exec.args").split()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task archiveReports(type: Zip) {
|
||||||
|
file("modules").traverse(type: groovy.io.FileType.DIRECTORIES, maxDepth: 1) { dir ->
|
||||||
|
if(new File(dir, "build.gradle").exists() && new File(dir, "/src/main/resources/reports").exists()) {
|
||||||
|
new File(dir, "/src/main/resources/reports/").listFiles().each { report ->
|
||||||
|
from report.getPath()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classifier 'reports'
|
||||||
|
includeEmptyDirs = false
|
||||||
|
destinationDir = file("$buildDir/libs")
|
||||||
|
}
|
||||||
|
|
||||||
|
war {
|
||||||
|
destinationDir = file("C:/apache-tomcat-8.5.0/webapps")
|
||||||
|
archiveName = "sophal2.war"
|
||||||
|
}
|
||||||
|
|
||||||
|
task stopTomcat(type: Exec) {
|
||||||
|
dependsOn stopTomcat
|
||||||
|
workingDir 'C:/apache-tomcat-8.5.0/bin'
|
||||||
|
commandLine 'cmd', '/c', 'shutdown.bat'
|
||||||
|
}
|
||||||
|
|
||||||
|
task startTomcat(type: Exec) {
|
||||||
|
dependsOn war
|
||||||
|
workingDir 'C:/apache-tomcat-8.5.0/bin'
|
||||||
|
commandLine 'cmd', '/c', 'startup.bat'
|
||||||
|
// commandLine 'cmd', '/c', 'start', '/b', 'startup.bat'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
build.finalizedBy archiveReports
|
||||||
51
docker-compose.yml
Normal file
51
docker-compose.yml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
environment:
|
||||||
|
- DB_HOST=db
|
||||||
|
- DB_PORT=5432
|
||||||
|
- DB_NAME=bdd_sophal
|
||||||
|
- DB_USER=postgres
|
||||||
|
- DB_PASSWORD=root
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:9.6
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: bdd_sophal
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: root
|
||||||
|
POSTGRES_HOST_AUTH_METHOD: trust
|
||||||
|
ports:
|
||||||
|
- "5433:5432"
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
- ./init-db:/docker-entrypoint-initdb.d
|
||||||
|
|
||||||
|
|
||||||
|
pgadmin:
|
||||||
|
image: dpage/pgadmin4
|
||||||
|
environment:
|
||||||
|
PGADMIN_DEFAULT_EMAIL: admin@admin.com
|
||||||
|
PGADMIN_DEFAULT_PASSWORD: admin
|
||||||
|
ports:
|
||||||
|
- "5050:80"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pgdata:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
backend:
|
||||||
22
gradle/style.gradle
Normal file
22
gradle/style.gradle
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories repos
|
||||||
|
dependencies {
|
||||||
|
classpath "com.diffplug.spotless:spotless-plugin-gradle:3.14.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: com.diffplug.gradle.spotless.SpotlessPlugin
|
||||||
|
|
||||||
|
spotless {
|
||||||
|
java {
|
||||||
|
target fileTree(projectDir) {
|
||||||
|
include '**/*.java'
|
||||||
|
exclude '**/build/**'
|
||||||
|
}
|
||||||
|
googleJavaFormat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task formatCode(dependsOn: ['licenseFormat', 'spotlessApply'])
|
||||||
|
|
||||||
|
build.dependsOn 'spotlessApply'
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip
|
||||||
172
gradlew
vendored
Normal file
172
gradlew
vendored
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
84
gradlew.bat
vendored
Normal file
84
gradlew.bat
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
16
modules/axelor-open-suite/.gitignore
vendored
Normal file
16
modules/axelor-open-suite/.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
bin
|
||||||
|
build
|
||||||
|
.gradle
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings
|
||||||
|
node_modules
|
||||||
|
application.min.*
|
||||||
|
*.sw[nop]
|
||||||
|
*~
|
||||||
|
.#*
|
||||||
|
[#]*#
|
||||||
|
.metadata/
|
||||||
|
.idea/
|
||||||
|
out/
|
||||||
|
*.iml
|
||||||
265
modules/axelor-open-suite/CHANGELOG.md
Normal file
265
modules/axelor-open-suite/CHANGELOG.md
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [5.2.1] - 2019-12-16
|
||||||
|
## Features
|
||||||
|
- ACCOUNTING REPORT: add new report, bank reconciliation statement.
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
- INVOICE: new mandatory labelling: Head office address.
|
||||||
|
- Company: Add tree view for companies.
|
||||||
|
- AdvancedExportLine: Add translation for field orderByType.
|
||||||
|
- PURCHASE REQUEST: add new columns in purchase request grid view.
|
||||||
|
- MOVE: changed position of reconciliation tag in move form.
|
||||||
|
- BANK STATEMENT: add caption under bank statement line grid in bank statement form in order to explain the colors are used in bank statement line grid.
|
||||||
|
- PRODUCT: update translation for "Service" and "Product".
|
||||||
|
- STOCK MOVE: empty reservation date time on duplicate stock move.
|
||||||
|
- STOCK MOVE: Update stock move's form view.
|
||||||
|
- SALE ORDER PRINTING: rename title "Sale order" to "Order Acknowledgement" of report on condition.
|
||||||
|
- MOVE: Improved messages when there is an exception on trying to remove an accounting move.
|
||||||
|
- Partner Form: change the french translation of "Create sale quotation".
|
||||||
|
- STOCK MOVE: empty to and from stock location set on company change.
|
||||||
|
- STOCK MOVE: hide reserved qty when it is a supplier arrival or a customer return.
|
||||||
|
- STOCK MOVE: rename title of stock-move-form buttons related to PFP.
|
||||||
|
- STOCK MOVE: update pfp tags on stock move form.
|
||||||
|
- Invoicing project: unit conversion for "Duration adjust for customer".
|
||||||
|
- ACCOUNTING REPORT: change the title of "General ledger 2" from the selection.
|
||||||
|
- TAX: Show type select in grid view.
|
||||||
|
- Sale order/quotation: fix tab title when generating a quotation from an opportunity.
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
- ANALYTIC: analytic journal in analytic line is now required.
|
||||||
|
- REFUND: avoid blocking message when ventilating the invoice.
|
||||||
|
- MOVE: fix display of status tag in move form.
|
||||||
|
- Manuf Order: fix real quantity not updating when a new line in consumed products is created.
|
||||||
|
- INVOICE PAYMENT CANCELLATION: corrected error when boolean allow removal validate move in account configuration is true.
|
||||||
|
- INVOICE: stopped the creation of invoice payment when a reconciliation is made with accounts not used in partner balance.
|
||||||
|
- User: find user by email using partner email address.
|
||||||
|
- Invoice: fix exception during passed for payment validation.
|
||||||
|
- Resolve NPE on stockMoveLines while displaying archived records.
|
||||||
|
- StockMove: set readonly to/fromStockLocation if status != Draft.
|
||||||
|
- INVOICE: remove the possibility for the user to manually link a stockMove to an invoice.
|
||||||
|
- PURCHASE ORDER LINE: isFilterOnSupplier is always true by default and can be set to false manually.
|
||||||
|
- INVOICE: Fix error on merging two invoices.
|
||||||
|
- Invoice: fix payment button visibility issue.
|
||||||
|
- HR: update insert leave method for mobile app.
|
||||||
|
- INVOICE: Fix printing of unit price when invoiceLine type is title.
|
||||||
|
- MOVE LINE: fix amount paid display in move line form.
|
||||||
|
- STOCK: ProductWorth computation fixed in ABCAnalysis.
|
||||||
|
- BASE: ABC Analysis Line with qty and worth equal to 0 are now removed.
|
||||||
|
- Fix Issues on EBICS user and partner form.
|
||||||
|
- Purchase Order: fix view budgetDistributionListPanel of purchaseOrderLine.
|
||||||
|
- Weighted Average Price: Fix computation issue causing an error in wap price.
|
||||||
|
- STOCK MOVE: fix the problem of partially invoiced qty in invoicing wizard form.
|
||||||
|
- STOCK CORRECTION: fixed error when qty is negative by reversing toStockLocation and fromStockLocation of created stock move.
|
||||||
|
- MASS INVOICING STOCK MOVE: fix error when selecting stock move to invoice.
|
||||||
|
|
||||||
|
## [5.2.0] - 2019-11-29
|
||||||
|
## Features
|
||||||
|
- Migration to Axelor Open Platform 5.2.
|
||||||
|
- Axelor-Business-Support: Addition of new module and app 'axelor-business-support'.
|
||||||
|
- Employee: added DPAE.
|
||||||
|
- TeamTask: added Frequency to be able to repeat tasks on given points in time.
|
||||||
|
- Employee: added wizard to create a new employee.
|
||||||
|
- SaleOrder: added possibility to invoice via generated task.
|
||||||
|
- Project: add support for project version.
|
||||||
|
- Project: add new form to create announcement for a given project.
|
||||||
|
- New menu and form stock correction allowing to fix a quantity in stock.
|
||||||
|
- User Form: Provide step wise view to create a user.
|
||||||
|
- TeamTask: Complete rework of team task model and views.
|
||||||
|
- Project: Complete rework of project model and views.
|
||||||
|
- Base: Addition of new object 'MailingListMessage' along with views, parent menu and sub-menus.
|
||||||
|
- InvoicingProject: Added new report 'InvoicingProjectAnnex.rptdesign' and attach to object on generating invoice.
|
||||||
|
- HR: Add CSV export support for Employment Contracts from its view and HR batch.
|
||||||
|
- Quality: Major improvements in axelor-quality module.
|
||||||
|
- QUALITY CONTROL: New report to print.
|
||||||
|
- AppBase: Add new configuration allowing to disable multi company support.
|
||||||
|
- OPPORTUNITY: Create event from opportunity.
|
||||||
|
- PROJECT: Add new feature allowing to create a template for a project.
|
||||||
|
- Invoice & PurchaseOrder: Added a budget overview.
|
||||||
|
- Advanced Import: Add feature to import data with advanced configurations.
|
||||||
|
- BPM: More than one workflow support for a same object.
|
||||||
|
- Sale Order/Sale Invoice: allow to change customer in existing invoice or order.
|
||||||
|
- MESSAGE TEMPLATE: added the management of additional contexts (groovy evaluation) in order to allow the use of Json fields.
|
||||||
|
- FORECAST RECAP: Add support of printing report in 'xls' and 'ods' format.
|
||||||
|
- PERIOD: Add a new popup when closing period to allow user to check and validate move lines.
|
||||||
|
- Stock Move: Add support for partial invoicing.
|
||||||
|
- ABC ANALYSIS: Add support for printing report in 'xls' type.
|
||||||
|
- Business Project: Add 'Project invoicing assistant' batch to update tasks and generate invoicing projects.
|
||||||
|
- Project Folder: Add two printings to display all project elements linked to the folder.
|
||||||
|
- Distance travelled calculation of kilometric expense line with Open street map.
|
||||||
|
- Timesheet: add timesheet reporting.
|
||||||
|
- Stock: Add stock history view for a given product, company and stock location.
|
||||||
|
- Production: Provide menu for Machine Planning.
|
||||||
|
- Company: Add employee Phonebook.
|
||||||
|
- Base: Addition of fields 'height' and 'width' in Company to change logo's dimension in Reports.
|
||||||
|
- Add a payment validator in supplier invoices.
|
||||||
|
|
||||||
|
## Improvements
|
||||||
|
- SaleOrder/Partner: adding new fields for comments on invoices, sale orders, purchase orders and deliveries.
|
||||||
|
- Timesheet: assign Task to lines when generating from Realise Planning.
|
||||||
|
- Timesheet: mark timesheet line as to be invoiced while generating it from Realise Planning.
|
||||||
|
- TeamTask: Add button to enter spent time.
|
||||||
|
- LogisticalForm: if config enabled, send an email on first save.
|
||||||
|
- MANUF. APP: new config to hide cost sheet group.
|
||||||
|
- Purchase Request: Add the possibility to select purchase orders.
|
||||||
|
- Production: Addition of two dummy fields to calculate sum of planned and real duration of operation orders.
|
||||||
|
- MOVE: improve reversion process.
|
||||||
|
- SaleOrder: task by product and task by line invoicing.
|
||||||
|
- SALE ORDER: Update in 'Quotations template' working process and view.
|
||||||
|
- DataBackup: Add possibility to restore date fields from a given relative date.
|
||||||
|
- PURCHASE ORDER LINES/INVOICE LINES: New fields related to budget.
|
||||||
|
- WEEKLY PLANNING: Add a type and minor changes.
|
||||||
|
- BULK UNIT COST CALCULATION: new way to compute all unit costs using BOM. Allow to compute cost using BOM level sequence.
|
||||||
|
- MRP: Generate new sequence on save.
|
||||||
|
- DataBackup: update importId when its null with format IDDDMMYYHHMM.
|
||||||
|
- Generating supplier order from partner form.
|
||||||
|
- Mobile App: Add configuration for quality app on mobile app.
|
||||||
|
- INVOICE: new process to print.
|
||||||
|
- PERMISSIONS: Display dashlets for groups/roles/users using the permission in permission and meta permission form views.
|
||||||
|
- OPPORTUNITY: Rename "opportunity type" to "type of need".
|
||||||
|
- INVOICE: Change form view's organization to match the SaleOrder view.
|
||||||
|
- PARTNER: Add link to employee form.
|
||||||
|
- PRICE LIST: Add dashlets to display partner.
|
||||||
|
- MRP: add boolean to exclude product without proposal in the result dashlet.
|
||||||
|
- HR: TRAINING - Optimization of the menu by adding filters
|
||||||
|
- MRP: Group proposals per supplier
|
||||||
|
- HR: rework training and recruitment menus.
|
||||||
|
- Data import: in the import file, add the possibility to fill selects either by values, title or translated titles.
|
||||||
|
- Action Builder: Add feature to create templates using json models to send email.
|
||||||
|
- FORECAST RECAP: sequence feature added for ForeCastRecap.
|
||||||
|
- Advance data import: Add new config to check if new configuration is added on file and do import according to file.
|
||||||
|
- UNIT: allows to translate name and label.
|
||||||
|
- STOCK RULE: Add template on StockRule and StockConfig used for mail notifications.
|
||||||
|
- CONFORMITY CERTIFICATE: display external reference on printing.
|
||||||
|
- TIMESHEET: new config to display line numbers.
|
||||||
|
- Advanced Import: Add support of imported records removal.
|
||||||
|
- SALE ORDER: Recompute unit price when hideDiscount is true.
|
||||||
|
- OPPORTUNITY: Auto fill sale-order form and cancel linked sale orders on 'closed lost' status.
|
||||||
|
- OBJECT DATA CONFIG: UX improvements and translations and change in export type.
|
||||||
|
- ANALYTIC MOVE LINE: project field title changed and domain filter added.
|
||||||
|
- CONTRACT: Set invoice date with newly added options for invoicing moment.
|
||||||
|
- Inventory: Manage different type of inventory: yearly or cycle turning.
|
||||||
|
- Address: Street have now a dedicated object.
|
||||||
|
- SALE ORDER / PURCHASE ORDER / INVOICES: Lines panel height set to 30.
|
||||||
|
- MOVE: add the possibility to choose a date while generating reverse move.
|
||||||
|
- Contract: Add analytic information to contract lines.
|
||||||
|
- MESSAGE TEMPLATE: help to suggest use of separator between email addresses.
|
||||||
|
- PRODUCTION ORDER: user can define manuf order's planned end date while creating production order from product form.
|
||||||
|
- PARTNER: new HTML field on partner for proforma.
|
||||||
|
- Contract: added button to manually close contract if termination date was set in the future.
|
||||||
|
- ContractLine: hide `isConsumptionLine` if not activated in Contract config.
|
||||||
|
- Employee: Add a creation workflow and allow to automatically create or link a user.
|
||||||
|
- TimesheetLine: Add reference to TeamTask and add time to charge field.
|
||||||
|
- Timesheet: Change tab title.
|
||||||
|
- Studio: Allowing to export all data without selecting any app builder.
|
||||||
|
- Studio: Custom model editor - Added title property for model and removed required condition for AppBuilder.
|
||||||
|
- MENUS: new organisation in CRM and Sales modules.
|
||||||
|
- Mobile: Add new app setting for 'Task'.
|
||||||
|
- JobPosition: Cannot open a position when status in on hold.
|
||||||
|
- Purchase Order: remove IPurchaseOrder deprecated class.
|
||||||
|
- Event: Allowing to suppress unsynchronized events.
|
||||||
|
- Employee: Add birth department and city of birth in employee.
|
||||||
|
- Employment Contract: Set form width to large.
|
||||||
|
- Contract: partner/project filters improved.
|
||||||
|
- APP BUILDER: Remove JsonCreator object.
|
||||||
|
- ContractBatch: Set default bankDetails of partner to created invoice bankDetails.
|
||||||
|
- PRICE LIST: hide historized price lists in pop-up view.
|
||||||
|
- MARKETING: Precise domain for model in message template.
|
||||||
|
- Change titles for productFamily.
|
||||||
|
- CONTRACT: Set project on generated invoices.
|
||||||
|
- ACCOUNT MOVE REVERSE: Selected reverse move date must not be after the date of the day
|
||||||
|
- ACCOUNT MOVE REVERSE: add the possibility to choose to hide or not the move lines (origin and reverse) in bank reconciliation
|
||||||
|
- Change google-plus icon by google one.
|
||||||
|
- Sale Order Line: Replacing 'price' with 'priceDiscounted' in a Grid View along with PurchaseOrderLine and InvoiceLine
|
||||||
|
- SUPPLY CHAIN: delete boolean manageInvoicedAmountByLine.
|
||||||
|
- FUNCTION: new object function on Sales and CRM and new M2O on partner
|
||||||
|
- CITIZENSHIP: Add new object citizenship on base and new M2O in country and employee
|
||||||
|
- EMPLOYEE: Files management added domains and demo data
|
||||||
|
- Inventory: Added calendar-view
|
||||||
|
- change term "Description" to "Comment" in english and "Commentaire" in french
|
||||||
|
- WEEKLY PLANNING: Days can be reordered and created.
|
||||||
|
- PROJECT / REPORTINGS: Addition of new dashboard - "Planned charge".
|
||||||
|
- INVENTORY: adding ODS file format in report selection type.
|
||||||
|
- Quality Control: Set default printing setting and update translation.
|
||||||
|
- INVOICE: Configure BIRT to generate an Excel and a Word file
|
||||||
|
- KEYWORD: remove Keyword model.
|
||||||
|
- Advanced Import: trim data before import.
|
||||||
|
- ACCOUNTING: year and accountSet fields are set empty when company is changed.
|
||||||
|
- ACCOUNTING CONFIGURATION AND REPORTED BALANCE: add a new journal parameter in accounting configuration named reported balance journal and this new parameter defines the journal used in the reported balance move line creation.
|
||||||
|
- PARTNER: Checks the consistency of the address list of a partner.
|
||||||
|
- EXCEPTION: Removing deprecated interface IException.
|
||||||
|
- PORTAL CLIENT: Add config to choose the type of connection (from ABS or external).
|
||||||
|
- DEMO DATA: Rename field data.
|
||||||
|
- ACCOUNTING BATCH: alert when the closing annual accounts batch already ran.
|
||||||
|
- CLIENT PORTAL: update the client form view.
|
||||||
|
- USER: Mass generation of random passwords.
|
||||||
|
- Advance data import: Set sequence of filetab and removed temporary file at the end which is created during the process.
|
||||||
|
- ACCOUNTING REPORT: add ODS file formate in report export type.
|
||||||
|
- FORECAST RECAP: reset fields while creating duplicate record.
|
||||||
|
- PICKING ORDER: new comment field for picking order on partner.
|
||||||
|
- INVOICE: Add field 'language' to change report language in company.
|
||||||
|
- QUALITY CONTROL: Add send email option when status is finished.
|
||||||
|
- EMPLOYEE: add emergency contact relationship.
|
||||||
|
- INVOICE PAYMENT: additionnal informations
|
||||||
|
- ACCOUNT CONFIG: update demo data for account config and 'is print invoices in company language' boolean is now at true by default.
|
||||||
|
- Contract: change filter on project field.
|
||||||
|
- TEAMTASKS: Creation from Same Order.
|
||||||
|
- PROJECT: show sub-menu project list when project type is empty.
|
||||||
|
- Financial Report: calculate total costs (per line) in chart and totals.
|
||||||
|
- ACCOUNTING REPORT: add Analytic general ledger.
|
||||||
|
- TIMETABLE: reworked timetables to have them work based on percentage of the order rather than on a per product basis. So far only for sale orders. Purchases to come.
|
||||||
|
- HRconfig: moved fields 'Health service' and 'Health service address' to HR module.
|
||||||
|
- STOCKMOVE: update stock move form view.
|
||||||
|
- MetaScheduler: fix MetaScheduler form-view in axelor-base module.
|
||||||
|
- AccountingReport: set configuration to display opening accounting moves default value to true.
|
||||||
|
- SUPPLYCHAIN: auto-complete sale order when it has been completely invoiced.
|
||||||
|
- Accounting situation: added two fields to manage the credit insurance.
|
||||||
|
- BoM: added a menu showing personalized bills of materials.
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
- Studio: Fix import app without image.
|
||||||
|
- Generation of Project/Phase from SaleOrder.
|
||||||
|
- Contract: Fix issue of not saving currentContractVersion fields in form view.
|
||||||
|
- ProductTaskTemplate: fix button display issue for edit and remove buttons on tree view.
|
||||||
|
- Employee: Fix issue of not saving each phase of creation process.
|
||||||
|
- Marketing: Fix error when trying to generate an event per target.
|
||||||
|
- Contract: Fix import error in data-init.
|
||||||
|
- BUSINESS PROJECT: Report printing Division by zero.
|
||||||
|
- UnitCostCalculation: Fixed the date format in the csv export name file.
|
||||||
|
- BONUS MGT: Fix formula variable error of human resource when computing amounts.
|
||||||
|
- INVOICE: Hide Due amount in report while printing "Original invoice / Updated copy".
|
||||||
|
- PurchaseOrder: Fill order date with sale order creation date when generating puchase order from sale order with interco.
|
||||||
|
- Purchase Order: Rename field 'priceDisplay' to 'displayPriceOnQuotationRequest'.
|
||||||
|
- INVOICE: Reduce font size of tax table in Invoice printing.
|
||||||
|
- PURCHASE ORDER PRINTING: display buyer email and phone as in sale order printing.
|
||||||
|
- ACCOUNT MOVE REVERSE: add translation.
|
||||||
|
- Transactionnal: correction and standardisation of rollback.
|
||||||
|
- CONFIGURATOR BOM: product, qty and unit are displayed in the grid-view.
|
||||||
|
- SALE ORDER LINE: fixed error when selecting a product.
|
||||||
|
- Studio: Fix readonly fields are enabled when imported an application.
|
||||||
|
- Studio: Fix error when click on wkf buttons.
|
||||||
|
- Studio: Fix export app.
|
||||||
|
- Advance Data Import: Fix indexOutOfBound Exception.
|
||||||
|
- Advanced Data Import: Specify truncated value to sampleLines for large string.
|
||||||
|
- REPORTED BALANCE: corrected abnormal amount in reported balance move lines if there was no partner associated to it.
|
||||||
|
- REPORTED BALANCE BATCH: the case where reported balance date on fiscal year is missing is now correctly managed.
|
||||||
|
- PURCHASE ORDER: fix issue in 'discountTypeSelect' of Purchase Order Line Form.
|
||||||
|
- Advanced Data import: fix issue of not generating info in log file when error occurred on import.
|
||||||
|
- Studio: fix m2o to metafile's widget property, display image,binarylink option.
|
||||||
|
- Advance data import: fix search issue, changed default import type of relational field to New and add import if condition for required Fields.
|
||||||
|
- Advance data import: Fix Data import error when there is same object in two different sheets.
|
||||||
|
- INVOICE: fix issue of invoice copy.
|
||||||
|
- TEAMTASK: Add fullname in demo data.
|
||||||
|
- Timesheet line: Duration label issue when created from mobile app.
|
||||||
|
- Purchase: Corrected translation of purchase not configured.
|
||||||
|
- SALEORDERLINE: Issue when Production module isn't installed.
|
||||||
|
- Invoice: replace field "irrecoverablestatusSelect" to "irrecoverableStatusSelect".
|
||||||
|
- SALE ORDER: fix error generating project without salemanUser.
|
||||||
|
- Advance Import: Resolve ArrayIndexOutOfBound exception.
|
||||||
|
- STOCK: Link back order with saleOrder or purchaseOrder.
|
||||||
|
- ADDRESS: when there is one address on partner it is treated as a default address.
|
||||||
|
- LEAVE REQUEST: Add error when leave reason has no unit.
|
||||||
|
- LEAVE REQUEST: Set duration value 0 if day planning of selected weekly planning is empty
|
||||||
|
|
||||||
|
[5.2.1]: https://github.com/axelor/axelor-open-suite/compare/v5.2.0...v5.2.1
|
||||||
|
[5.2.0]: https://github.com/axelor/axelor-open-suite/compare/v5.1.13...v5.2.0
|
||||||
95
modules/axelor-open-suite/CONTRIBUTING.md
Normal file
95
modules/axelor-open-suite/CONTRIBUTING.md
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# Contributing Guide
|
||||||
|
|
||||||
|
We’d love for you to contribute to our source code and to make app even better.
|
||||||
|
While we try to keep requirements for contributing to a minimum,
|
||||||
|
there are a few guidelines we’d like you to follow:
|
||||||
|
|
||||||
|
* [Contributor License Agreement](#contributor-license-agreement)
|
||||||
|
* [Reporting Issues](#reporting-issues)
|
||||||
|
* [Submitting](#submitting)
|
||||||
|
* [Code of Conduct](#code-of-conduct)
|
||||||
|
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
By submitting code as an individual you agree to the [individual contributor license agreement][individual-cla].
|
||||||
|
By submitting code as an entity you agree to the [corporate contributor license agreement][corporate-cla].
|
||||||
|
|
||||||
|
## Reporting Issues
|
||||||
|
|
||||||
|
Before you submit your issue search the archive, maybe your question was already answered.
|
||||||
|
|
||||||
|
If your issue appears to be a bug, and hasn't been reported, open a new issue.
|
||||||
|
Help us to maximize the effort we can spend fixing issues and adding new features,
|
||||||
|
by not reporting duplicate issues. Providing the following information will increase
|
||||||
|
the chances of your issue being dealt with quickly:
|
||||||
|
|
||||||
|
* **Use Case** – explain your use case
|
||||||
|
* **Overview of the issue** – include stacktrace
|
||||||
|
* **Version** – which version you are using?
|
||||||
|
* **Browsers and Operating System** – is this a problem with all browsers?
|
||||||
|
* **Reproduce the Error** – provide a patch against app to reproduce the error
|
||||||
|
* **Related Issues** – has a similar issue been reported before?
|
||||||
|
* **Suggest a Fix** – you can point to what might be causing the problem (line of code or commit)
|
||||||
|
|
||||||
|
Please make sure you don’t post any sensitive information while reporting issues.
|
||||||
|
|
||||||
|
## Submitting
|
||||||
|
|
||||||
|
* [Fork](https://help.github.com/articles/fork-a-repo/) the repo.
|
||||||
|
* Code!
|
||||||
|
* Push your changes to the topic branch in your fork of the repository.
|
||||||
|
* Initiate a [pull request](http://help.github.com/send-pull-requests/)
|
||||||
|
* Update the issue, adding a comment including a link to the created pull request
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
As contributors and maintainers of this project, and in the interest of
|
||||||
|
fostering an open and welcoming community, we pledge to respect all people who
|
||||||
|
contribute through reporting issues, posting feature requests, updating
|
||||||
|
documentation, submitting pull requests or patches, and other activities.
|
||||||
|
|
||||||
|
We are committed to making participation in this project a harassment-free
|
||||||
|
experience for everyone, regardless of level of experience, gender, gender
|
||||||
|
identity and expression, sexual orientation, disability, personal appearance,
|
||||||
|
body size, race, ethnicity, age, religion, or nationality.
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery
|
||||||
|
* Personal attacks
|
||||||
|
* Trolling or insulting/derogatory comments
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing other's private information, such as physical or electronic
|
||||||
|
addresses, without explicit permission
|
||||||
|
* Other unethical or unprofessional conduct
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
By adopting this Code of Conduct, project maintainers commit themselves to
|
||||||
|
fairly and consistently applying these principles to every aspect of managing
|
||||||
|
this project. Project maintainers who do not follow or enforce the Code of
|
||||||
|
Conduct may be permanently removed from the project team.
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
|
when an individual is representing the project or its community.
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting a project maintainer at [conduct@axelor.com][mail]. All
|
||||||
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
|
is deemed necessary and appropriate to the circumstances. Maintainers are
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an
|
||||||
|
incident.
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 1.3.0, available at
|
||||||
|
[http://contributor-covenant.org/version/1/3/0/][version]
|
||||||
|
|
||||||
|
[mail]: mailto:conduct@axelor.com
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/3/0/
|
||||||
|
[individual-cla]: http://axelor.com/cla/individuel-cla/
|
||||||
|
[corporate-cla]: http://axelor.com/cla/corporate-cla/
|
||||||
669
modules/axelor-open-suite/LICENSE
Normal file
669
modules/axelor-open-suite/LICENSE
Normal file
@ -0,0 +1,669 @@
|
|||||||
|
Axelor is published under the GNU AFFERO GENERAL PUBLIC LICENSE, Version 3
|
||||||
|
(AGPLv3), as included below. Some external libraries and contributions bundled
|
||||||
|
with Axelor may be published under other AGPLv3-compatible licenses. For
|
||||||
|
these, please refer to the relevant source files and/or license files, in the
|
||||||
|
source code tree.
|
||||||
|
|
||||||
|
**************************************************************************
|
||||||
|
|
||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
27
modules/axelor-open-suite/README.md
Normal file
27
modules/axelor-open-suite/README.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Axelor Open Suite
|
||||||
|
================================
|
||||||
|
|
||||||
|
Axelor Open Suite reduces the complexity and improve responsiveness of business processes. Thanks to its modularity, you can start with few features and then activate other modules when needed.
|
||||||
|
|
||||||
|
Axelor Open Suite includes the following modules :
|
||||||
|
|
||||||
|
* Customer Relationship Management
|
||||||
|
* Sales management
|
||||||
|
* Financial and cost management
|
||||||
|
* Human Resource Management
|
||||||
|
* Project Management
|
||||||
|
* Inventory and Supply Chain Management
|
||||||
|
* Production Management
|
||||||
|
* Multi-company, multi-currency and multi-lingual
|
||||||
|
|
||||||
|
Axelor Open Suite is built on top of [Axelor Open Platform](https://github.com/axelor/axelor-open-platform)
|
||||||
|
|
||||||
|
Code Format
|
||||||
|
================================
|
||||||
|
|
||||||
|
Axelor follows Google Code Format.
|
||||||
|
Tools:
|
||||||
|
* Gradle Task: ./gradlew spotlessApply
|
||||||
|
* IDE plugin
|
||||||
|
* [Eclipse](https://github.com/google/google-java-format#eclipse)
|
||||||
|
* [IntelliJ](https://github.com/google/google-java-format#intellij)
|
||||||
27
modules/axelor-open-suite/axelor-account/build.gradle
Normal file
27
modules/axelor-open-suite/axelor-account/build.gradle
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
apply plugin: "com.axelor.app-module"
|
||||||
|
|
||||||
|
apply from: "../version.gradle"
|
||||||
|
|
||||||
|
apply {
|
||||||
|
version = openSuiteVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
axelor {
|
||||||
|
title "Axelor Account"
|
||||||
|
description "Axelor Account Module"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(":modules:axelor-base")
|
||||||
|
compile project(":modules:axelor-purchase")
|
||||||
|
compile 'xalan:xalan:2.7.2'
|
||||||
|
|
||||||
|
testImplementation 'org.mockito:mockito-core:4.8.0' // Or latest version
|
||||||
|
|
||||||
|
|
||||||
|
compile group: 'jdom', name: 'jdom', version: '1.1'
|
||||||
|
compile group: 'org.apache.xmlbeans', name: 'xmlbeans', version: '2.5.0'
|
||||||
|
compile "org.bouncycastle:bcprov-jdk15on:1.62"
|
||||||
|
compile "org.bouncycastle:bcpkix-jdk15on:1.62"
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class AccountAccountRepository extends AccountRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account save(Account account) {
|
||||||
|
try {
|
||||||
|
if (account.getId() == null) {
|
||||||
|
return super.save(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account.getReconcileOk()) {
|
||||||
|
Set<Account> accountList = account.getCompatibleAccountSet();
|
||||||
|
|
||||||
|
if (accountList != null) {
|
||||||
|
for (Account acc : accountList) {
|
||||||
|
acc.setReconcileOk(true);
|
||||||
|
acc.addCompatibleAccountSetItem(account);
|
||||||
|
JPA.save(acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (account.getCompatibleAccountSet() != null) {
|
||||||
|
for (Account acc : account.getCompatibleAccountSet()) {
|
||||||
|
acc.removeCompatibleAccountSetItem(account);
|
||||||
|
if (acc.getCompatibleAccountSet().size() == 0) {
|
||||||
|
acc.setReconcileOk(false);
|
||||||
|
}
|
||||||
|
JPA.save(acc);
|
||||||
|
}
|
||||||
|
account.getCompatibleAccountSet().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.save(account);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountingBatch;
|
||||||
|
|
||||||
|
public class AccountingBatchAccountRepository extends AccountingBatchRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccountingBatch copy(AccountingBatch entity, boolean deep) {
|
||||||
|
AccountingBatch copy = super.copy(entity, deep);
|
||||||
|
copy.setBatchList(null);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountingReport;
|
||||||
|
import com.axelor.apps.account.service.AccountingReportService;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import com.axelor.exception.service.TraceBackService;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class AccountingReportManagementRepository extends AccountingReportRepository {
|
||||||
|
|
||||||
|
@Inject protected AccountingReportService accountingReportService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccountingReport save(AccountingReport accountingReport) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (accountingReport.getRef() == null) {
|
||||||
|
|
||||||
|
String seq = accountingReportService.getSequence(accountingReport);
|
||||||
|
accountingReportService.setSequence(accountingReport, seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.save(accountingReport);
|
||||||
|
} catch (Exception e) {
|
||||||
|
JPA.em().getTransaction().rollback();
|
||||||
|
JPA.runInTransaction(() -> TraceBackService.trace(e));
|
||||||
|
JPA.em().getTransaction().begin();
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccountingReport copy(AccountingReport entity, boolean deep) {
|
||||||
|
|
||||||
|
AccountingReport copy = super.copy(entity, deep);
|
||||||
|
|
||||||
|
copy.setRef(null);
|
||||||
|
copy.setStatusSelect(this.STATUS_DRAFT);
|
||||||
|
copy.setPublicationDateTime(null);
|
||||||
|
copy.setTotalDebit(BigDecimal.ZERO);
|
||||||
|
copy.setTotalCredit(BigDecimal.ZERO);
|
||||||
|
copy.setBalance(BigDecimal.ZERO);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AnalyticMoveLine;
|
||||||
|
|
||||||
|
public class AnalyticMoveLineMngtRepository extends AnalyticMoveLineRepository {
|
||||||
|
@Override
|
||||||
|
public AnalyticMoveLine copy(AnalyticMoveLine entity, boolean deep) {
|
||||||
|
AnalyticMoveLine copy = super.copy(entity, deep);
|
||||||
|
copy.setMoveLine(null);
|
||||||
|
copy.setInvoiceLine(null);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.DepositSlip;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.base.db.Sequence;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.exception.service.TraceBackService;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class DepositSlipAccountRepository extends DepositSlipRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DepositSlip save(DepositSlip entity) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (Strings.isNullOrEmpty(entity.getDepositNumber())) {
|
||||||
|
setDepositNumber(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.save(entity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
TraceBackService.trace(e);
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDepositNumber(DepositSlip entity) throws AxelorException {
|
||||||
|
SequenceService sequenceService = Beans.get(SequenceService.class);
|
||||||
|
String depositNumber =
|
||||||
|
sequenceService.getSequenceNumber(SequenceRepository.DEPOSIT_SLIP, entity.getCompany());
|
||||||
|
|
||||||
|
if (Strings.isNullOrEmpty(depositNumber)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
Sequence.class,
|
||||||
|
TraceBackRepository.CATEGORY_NO_VALUE,
|
||||||
|
I18n.get(IExceptionMessage.DEPOSIT_SLIP_MISSING_SEQUENCE),
|
||||||
|
entity.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setDepositNumber(depositNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(DepositSlip entity) {
|
||||||
|
if (entity.getPublicationDate() != null) {
|
||||||
|
throw new PersistenceException(I18n.get(IExceptionMessage.DEPOSIT_SLIP_CANNOT_DELETE));
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.clearPaymentVoucherList();
|
||||||
|
super.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.FixedAsset;
|
||||||
|
import com.axelor.apps.account.service.FixedAssetService;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class FixedAssetManagementRepository extends FixedAssetRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FixedAsset save(FixedAsset fixedAsset) {
|
||||||
|
try {
|
||||||
|
computeReference(fixedAsset);
|
||||||
|
computeDepreciation(fixedAsset);
|
||||||
|
return super.save(fixedAsset);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new PersistenceException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeReference(FixedAsset fixedAsset) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (fixedAsset.getId() != null && Strings.isNullOrEmpty(fixedAsset.getReference())) {
|
||||||
|
fixedAsset.setReference(
|
||||||
|
Beans.get(SequenceService.class).getDraftSequenceNumber(fixedAsset));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeDepreciation(FixedAsset fixedAsset) {
|
||||||
|
if ((fixedAsset.getFixedAssetLineList() == null || fixedAsset.getFixedAssetLineList().isEmpty())
|
||||||
|
&& fixedAsset.getGrossValue().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
|
||||||
|
Beans.get(FixedAssetService.class).generateAndcomputeLines(fixedAsset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FixedAsset copy(FixedAsset entity, boolean deep) {
|
||||||
|
|
||||||
|
FixedAsset copy = super.copy(entity, deep);
|
||||||
|
copy.setStatusSelect(STATUS_DRAFT);
|
||||||
|
copy.setReference(null);
|
||||||
|
copy.setResidualValue(entity.getGrossValue());
|
||||||
|
copy.setFixedAssetLineList(null);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.InvoiceBatch;
|
||||||
|
|
||||||
|
public class InvoiceBatchAccountRepository extends InvoiceBatchRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InvoiceBatch copy(InvoiceBatch entity, boolean deep) {
|
||||||
|
InvoiceBatch copy = super.copy(entity, deep);
|
||||||
|
copy.setBatchList(null);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.SubrogationRelease;
|
||||||
|
import com.axelor.apps.account.service.invoice.InvoiceService;
|
||||||
|
import com.axelor.exception.service.TraceBackService;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class InvoiceManagementRepository extends InvoiceRepository {
|
||||||
|
@Override
|
||||||
|
public Invoice copy(Invoice entity, boolean deep) {
|
||||||
|
|
||||||
|
Invoice copy = super.copy(entity, deep);
|
||||||
|
|
||||||
|
copy.setStatusSelect(STATUS_DRAFT);
|
||||||
|
copy.setInvoiceId(null);
|
||||||
|
copy.setInvoiceDate(null);
|
||||||
|
copy.setDueDate(null);
|
||||||
|
copy.setValidatedByUser(null);
|
||||||
|
copy.setMove(null);
|
||||||
|
copy.setOriginalInvoice(null);
|
||||||
|
copy.setCompanyInTaxTotalRemaining(BigDecimal.ZERO);
|
||||||
|
copy.setAmountPaid(BigDecimal.ZERO);
|
||||||
|
copy.setIrrecoverableStatusSelect(IRRECOVERABLE_STATUS_NOT_IRRECOUVRABLE);
|
||||||
|
copy.setAmountRejected(BigDecimal.ZERO);
|
||||||
|
copy.clearBatchSet();
|
||||||
|
copy.setDebitNumber(null);
|
||||||
|
copy.setDirectDebitManagement(null);
|
||||||
|
copy.setDoubtfulCustomerOk(false);
|
||||||
|
copy.setMove(null);
|
||||||
|
copy.setInterbankCodeLine(null);
|
||||||
|
copy.setPaymentMove(null);
|
||||||
|
copy.clearRefundInvoiceList();
|
||||||
|
copy.setRejectDate(null);
|
||||||
|
copy.setOriginalInvoice(null);
|
||||||
|
copy.setUsherPassageOk(false);
|
||||||
|
copy.setAlreadyPrintedOk(false);
|
||||||
|
copy.setCanceledPaymentSchedule(null);
|
||||||
|
copy.setDirectDebitAmount(BigDecimal.ZERO);
|
||||||
|
copy.setImportId(null);
|
||||||
|
copy.setPartnerAccount(null);
|
||||||
|
copy.setJournal(null);
|
||||||
|
copy.clearInvoicePaymentList();
|
||||||
|
copy.setPrintedPDF(null);
|
||||||
|
copy.setValidatedDate(null);
|
||||||
|
copy.setVentilatedByUser(null);
|
||||||
|
copy.setVentilatedDate(null);
|
||||||
|
copy.setPfpValidateStatusSelect(PFP_STATUS_AWAITING);
|
||||||
|
copy.setDecisionPfpTakenDate(null);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Invoice save(Invoice invoice) {
|
||||||
|
try {
|
||||||
|
invoice = super.save(invoice);
|
||||||
|
Beans.get(InvoiceService.class).setSequence(invoice);
|
||||||
|
|
||||||
|
return invoice;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> populate(Map<String, Object> json, Map<String, Object> context) {
|
||||||
|
try {
|
||||||
|
if (context.get("_model") != null
|
||||||
|
&& context.get("_model").toString().contains("SubrogationRelease")) {
|
||||||
|
long id = (long) context.get("id");
|
||||||
|
SubrogationRelease subrogationRelease =
|
||||||
|
Beans.get(SubrogationReleaseRepository.class).find(id);
|
||||||
|
json.put("$subrogationStatusSelect", subrogationRelease.getStatusSelect());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
TraceBackService.trace(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.populate(json, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.InvoicePayment;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentValidateService;
|
||||||
|
import com.axelor.exception.service.TraceBackService;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class InvoicePaymentManagementRepository extends InvoicePaymentRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InvoicePayment save(InvoicePayment invoicePayment) {
|
||||||
|
try {
|
||||||
|
Beans.get(InvoicePaymentValidateService.class).validate(invoicePayment);
|
||||||
|
return super.save(invoicePayment);
|
||||||
|
} catch (Exception e) {
|
||||||
|
TraceBackService.trace(e);
|
||||||
|
throw new PersistenceException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
|
||||||
|
public class JournalManagementRepository extends JournalRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Journal copy(Journal entity, boolean deep) {
|
||||||
|
|
||||||
|
Journal copy = super.copy(entity, deep);
|
||||||
|
|
||||||
|
copy.setStatusSelect(JournalRepository.STATUS_INACTIVE);
|
||||||
|
copy.setSequence(null);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AnalyticMoveLine;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.move.MoveLineService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class MoveLineManagementRepository extends MoveLineRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(MoveLine entity) {
|
||||||
|
if (!entity.getMove().getStatusSelect().equals(MoveRepository.STATUS_NEW)) {
|
||||||
|
try {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.MOVE_REMOVE_NOT_OK),
|
||||||
|
entity.getMove().getReference());
|
||||||
|
} catch (AxelorException e) {
|
||||||
|
throw new PersistenceException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MoveLine save(MoveLine entity) {
|
||||||
|
List<AnalyticMoveLine> analyticMoveLineList = entity.getAnalyticMoveLineList();
|
||||||
|
if (analyticMoveLineList != null) {
|
||||||
|
for (AnalyticMoveLine analyticMoveLine : analyticMoveLineList) {
|
||||||
|
analyticMoveLine.setAccount(entity.getAccount());
|
||||||
|
analyticMoveLine.setAccountType(entity.getAccount().getAccountType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Beans.get(MoveLineService.class).validateMoveLine(entity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e);
|
||||||
|
}
|
||||||
|
return super.save(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AnalyticMoveLine;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.move.MoveSequenceService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveValidateService;
|
||||||
|
import com.axelor.apps.base.db.Period;
|
||||||
|
import com.axelor.apps.base.db.repo.YearRepository;
|
||||||
|
import com.axelor.apps.base.service.PeriodService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class MoveManagementRepository extends MoveRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Move copy(Move entity, boolean deep) {
|
||||||
|
|
||||||
|
Move copy = super.copy(entity, deep);
|
||||||
|
|
||||||
|
copy.setDate(Beans.get(AppBaseService.class).getTodayDate());
|
||||||
|
|
||||||
|
Period period = null;
|
||||||
|
try {
|
||||||
|
period =
|
||||||
|
Beans.get(PeriodService.class)
|
||||||
|
.getActivePeriod(copy.getDate(), entity.getCompany(), YearRepository.TYPE_FISCAL);
|
||||||
|
} catch (AxelorException e) {
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
copy.setStatusSelect(STATUS_NEW);
|
||||||
|
copy.setReference(null);
|
||||||
|
copy.setExportNumber(null);
|
||||||
|
copy.setExportDate(null);
|
||||||
|
copy.setAccountingReport(null);
|
||||||
|
copy.setValidationDate(null);
|
||||||
|
copy.setPeriod(period);
|
||||||
|
copy.setAccountingOk(false);
|
||||||
|
copy.setIgnoreInDebtRecoveryOk(false);
|
||||||
|
copy.setPaymentVoucher(null);
|
||||||
|
copy.setRejectOk(false);
|
||||||
|
copy.setInvoice(null);
|
||||||
|
|
||||||
|
List<MoveLine> moveLineList = copy.getMoveLineList();
|
||||||
|
|
||||||
|
if (moveLineList != null) {
|
||||||
|
moveLineList.forEach(moveLine -> resetMoveLine(moveLine, copy.getDate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetMoveLine(MoveLine moveLine, LocalDate date) {
|
||||||
|
moveLine.setInvoiceReject(null);
|
||||||
|
moveLine.setDate(date);
|
||||||
|
moveLine.setExportedDirectDebitOk(false);
|
||||||
|
moveLine.setReimbursementStatusSelect(MoveLineRepository.REIMBURSEMENT_STATUS_NULL);
|
||||||
|
|
||||||
|
List<AnalyticMoveLine> analyticMoveLineList = moveLine.getAnalyticMoveLineList();
|
||||||
|
|
||||||
|
if (analyticMoveLineList != null) {
|
||||||
|
moveLine.getAnalyticMoveLineList().forEach(line -> line.setDate(moveLine.getDate()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Move save(Move move) {
|
||||||
|
try {
|
||||||
|
if (move.getStatusSelect() == MoveRepository.STATUS_DAYBOOK) {
|
||||||
|
Beans.get(MoveValidateService.class).checkPreconditions(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
Beans.get(MoveSequenceService.class).setDraftSequence(move);
|
||||||
|
List<MoveLine> moveLineList = move.getMoveLineList();
|
||||||
|
if (moveLineList != null) {
|
||||||
|
for (MoveLine moveLine : moveLineList) {
|
||||||
|
List<AnalyticMoveLine> analyticMoveLineList = moveLine.getAnalyticMoveLineList();
|
||||||
|
if (analyticMoveLineList != null) {
|
||||||
|
for (AnalyticMoveLine analyticMoveLine : analyticMoveLineList) {
|
||||||
|
analyticMoveLine.setAccount(moveLine.getAccount());
|
||||||
|
analyticMoveLine.setAccountType(moveLine.getAccount().getAccountType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.save(move);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Move entity) {
|
||||||
|
|
||||||
|
if (!entity.getStatusSelect().equals(MoveRepository.STATUS_NEW)) {
|
||||||
|
try {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.MOVE_REMOVE_NOT_OK),
|
||||||
|
entity.getReference());
|
||||||
|
} catch (AxelorException e) {
|
||||||
|
throw new PersistenceException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountingSituation;
|
||||||
|
import com.axelor.apps.account.service.AccountingSituationService;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.repo.PartnerBaseRepository;
|
||||||
|
import com.axelor.apps.base.db.repo.PartnerRepository;
|
||||||
|
import com.axelor.apps.base.service.app.AppService;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class PartnerAccountRepository extends PartnerBaseRepository {
|
||||||
|
|
||||||
|
private AppService appService;
|
||||||
|
|
||||||
|
private AccountingSituationService accountingSituationService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PartnerAccountRepository(
|
||||||
|
AppService appService, AccountingSituationService accountingSituationService) {
|
||||||
|
this.appService = appService;
|
||||||
|
this.accountingSituationService = accountingSituationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Partner save(Partner partner) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (partner.getId() == null) {
|
||||||
|
partner = super.save(partner);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appService.isApp("account")) {
|
||||||
|
if (partner.getIsContact() == false || partner.getIsEmployee()) {
|
||||||
|
// Create & fill
|
||||||
|
Beans.get(AccountingSituationService.class)
|
||||||
|
.createAccountingSituation(Beans.get(PartnerRepository.class).find(partner.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do this for contacts too as it seems this is the way employees are handled
|
||||||
|
if (CollectionUtils.isNotEmpty(partner.getAccountingSituationList())) {
|
||||||
|
for (AccountingSituation situation : partner.getAccountingSituationList()) {
|
||||||
|
accountingSituationService.createPartnerAccounts(situation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.save(partner);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Partner copy(Partner partner, boolean deep) {
|
||||||
|
|
||||||
|
Partner copy = super.copy(partner, deep);
|
||||||
|
|
||||||
|
if (appService.isApp("account")) {
|
||||||
|
copy.setAccountingSituationList(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.PaymentVoucher;
|
||||||
|
import com.axelor.apps.account.service.payment.paymentvoucher.PaymentVoucherSequenceService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.exception.service.TraceBackService;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class PaymentVoucherManagementRepository extends PaymentVoucherRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PaymentVoucher copy(PaymentVoucher entity, boolean deep) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copy set are commented because there is a lot of vouchers that contains the same element to pay but partially
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaymentVoucher copy = super.copy(entity, deep);
|
||||||
|
|
||||||
|
copy.setStatusSelect(STATUS_DRAFT);
|
||||||
|
copy.setRef(null);
|
||||||
|
copy.setPaymentDate(Beans.get(AppBaseService.class).getTodayDate());
|
||||||
|
// copy.clearPayVoucherDueElementList();
|
||||||
|
// copy.clearPayVoucherElementToPayList();
|
||||||
|
copy.setGeneratedMove(null);
|
||||||
|
copy.setBankCardTransactionNumber(null);
|
||||||
|
copy.clearBatchSet();
|
||||||
|
copy.setImportId(null);
|
||||||
|
copy.setReceiptNo(null);
|
||||||
|
// copy.setRemainingAmount(null);
|
||||||
|
// copy.setRemainingAllocatedAmount(null);
|
||||||
|
copy.setToSaveEmailOk(false);
|
||||||
|
copy.setDefaultEmailOk(false);
|
||||||
|
copy.setEmail(null);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PaymentVoucher save(PaymentVoucher paymentVoucher) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
Beans.get(PaymentVoucherSequenceService.class).setReference(paymentVoucher);
|
||||||
|
|
||||||
|
return super.save(paymentVoucher);
|
||||||
|
} catch (Exception e) {
|
||||||
|
TraceBackService.trace(e);
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.ReconcileGroup;
|
||||||
|
import com.axelor.apps.account.service.ReconcileGroupSequenceService;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class ReconcileGroupAccountRepository extends ReconcileGroupRepository {
|
||||||
|
|
||||||
|
/** On first reconcile group save (e.g. when the code is not filled), we fill the sequence. */
|
||||||
|
@Override
|
||||||
|
public ReconcileGroup save(ReconcileGroup reconcileGroup) {
|
||||||
|
try {
|
||||||
|
if (Strings.isNullOrEmpty(reconcileGroup.getCode())) {
|
||||||
|
Beans.get(ReconcileGroupSequenceService.class).fillCodeFromSequence(reconcileGroup);
|
||||||
|
}
|
||||||
|
return super.save(reconcileGroup);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.ReconcileSequenceService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
public class ReconcileManagementRepository extends ReconcileRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reconcile save(Reconcile reconcile) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
Beans.get(ReconcileSequenceService.class).setDraftSequence(reconcile);
|
||||||
|
|
||||||
|
return super.save(reconcile);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PersistenceException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reconcile copy(Reconcile reconcile, boolean deep) {
|
||||||
|
|
||||||
|
Reconcile copy = super.copy(reconcile, deep);
|
||||||
|
|
||||||
|
copy.setCanBeZeroBalanceOk(false);
|
||||||
|
copy.setMustBeZeroBalanceOk(false);
|
||||||
|
copy.setReconcileSeq(null);
|
||||||
|
copy.setStatusSelect(ReconcileRepository.STATUS_DRAFT);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Reconcile entity) {
|
||||||
|
|
||||||
|
if (!entity.getStatusSelect().equals(ReconcileRepository.STATUS_DRAFT)) {
|
||||||
|
try {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_CAN_NOT_BE_REMOVE),
|
||||||
|
entity.getReconcileSeq());
|
||||||
|
} catch (AxelorException e) {
|
||||||
|
throw new PersistenceException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.db.repo;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.SubrogationRelease;
|
||||||
|
|
||||||
|
public class SubrogationReleaseManagementRepository extends SubrogationReleaseRepository {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubrogationRelease copy(SubrogationRelease entity, boolean deep) {
|
||||||
|
|
||||||
|
SubrogationRelease srCopy = super.copy(entity, deep);
|
||||||
|
|
||||||
|
srCopy.setStatusSelect(STATUS_NEW);
|
||||||
|
srCopy.clearInvoiceSet();
|
||||||
|
|
||||||
|
return srCopy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,804 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface of Exceptions. Enum all exception of axelor-account.
|
||||||
|
*
|
||||||
|
* @author dubaux
|
||||||
|
*/
|
||||||
|
public interface IExceptionMessage {
|
||||||
|
|
||||||
|
static final String INVOICE_LINE_TAX_LINE = /*$$(*/ "A tax line is missing" /*)*/;
|
||||||
|
/** Bank statement service */
|
||||||
|
static final String BANK_STATEMENT_1 = /*$$(*/
|
||||||
|
"%s : Computed balance and Ending Balance must be equal" /*)*/;
|
||||||
|
|
||||||
|
static final String BANK_STATEMENT_2 = /*$$(*/
|
||||||
|
"%s : MoveLine amount is not equals with bank statement line %s" /*)*/;
|
||||||
|
static final String BANK_STATEMENT_3 = /*$$(*/
|
||||||
|
"%s : Bank statement line %s amount can't be null" /*)*/;
|
||||||
|
|
||||||
|
/** Move service */
|
||||||
|
static final String NO_MOVES_SELECTED = /*$$(*/
|
||||||
|
"Please select 'Draft' or 'Simulated' moves" /*)*/;
|
||||||
|
|
||||||
|
static final String MOVE_VALIDATION_NOT_OK = /*$$(*/
|
||||||
|
"Error in move validation, please check the log" /*)*/;
|
||||||
|
static final String MOVE_VALIDATION_OK = /*$$(*/ "Moves validated successfully" /*)*/;
|
||||||
|
static final String MOVE_ARCHIVE_NOT_OK = /*$$(*/ "You can't archive this move %s" /*)*/;
|
||||||
|
static final String MOVE_REMOVE_NOT_OK = /*$$(*/ "You can't remove this move %s" /*)*/;
|
||||||
|
static final String MOVE_REMOVED_OK = /*$$(*/ "Move(s) has been removed successfully" /*)*/;
|
||||||
|
static final String MOVE_ARCHIVE_OK = /*$$(*/ "Move(s) has been archived successfully" /*)*/;
|
||||||
|
static final String NO_MOVE_TO_REMOVE_OR_ARCHIVE = /*$$(*/
|
||||||
|
"Please select 'Draft' or 'Daybook' or 'Canceled' moves" /*)*/;
|
||||||
|
static final String MOVE_ARCHIVE_OR_REMOVE_OK = /*$$(*/
|
||||||
|
"Move(s) has been removed or archived successfully" /*)*/;
|
||||||
|
static final String MOVE_ARCHIVE_OR_REMOVE_NOT_OK = /*$$(*/
|
||||||
|
"Error in move deleting or archiving, please check the log" /*)*/;
|
||||||
|
static final String MOVE_ARCHIVE_NOT_OK_BECAUSE_OF_LINK_WITH = /*$$(*/
|
||||||
|
"This move %s can not be archived because it is linked to another piece named %s." /*)*/;
|
||||||
|
static final String MOVE_LINE_ARCHIVE_NOT_OK_BECAUSE_OF_LINK_WITH = /*$$(*/
|
||||||
|
"This move line %s can not be archived because it is linked to another piece named %s." /*)*/;
|
||||||
|
static final String MOVE_ARCHIVE_OR_REMOVE_NOT_OK_NB = /*$$(*/
|
||||||
|
"%d moves couldn't be deleted or archived, please check the logs." /*)*/;
|
||||||
|
|
||||||
|
/** Account management service */
|
||||||
|
static final String ACCOUNT_MANAGEMENT_1_ACCOUNT = /*$$(*/
|
||||||
|
"Accounting configuration is missing for Product: %s (company: %s)" /*)*/;
|
||||||
|
|
||||||
|
/** AccountingSituationService * */
|
||||||
|
static final String ACCOUNTING_SITUATION_1 = /*$$(*/
|
||||||
|
"You have to enter a prefix for automatic customer account creation in accounting application parameters of company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String ACCOUNTING_SITUATION_2 = /*$$(*/
|
||||||
|
"You have to select a sequence for automatic customer account creation in accounting application parameters of company %s" /*)*/;
|
||||||
|
static final String ACCOUNTING_SITUATION_3 = /*$$(*/
|
||||||
|
"Invalid automatic partner account creation mode, this is a bug that should be reported." /*)*/;
|
||||||
|
static final String ACCOUNTING_SITUATION_4 = /*$$(*/
|
||||||
|
"You have to enter a prefix for automatic supplier account creation in accounting application parameters of company %s" /*)*/;
|
||||||
|
static final String ACCOUNTING_SITUATION_5 = /*$$(*/
|
||||||
|
"You have to select a sequence for automatic supplier account creation in accounting application parameters of company %s" /*)*/;
|
||||||
|
static final String ACCOUNTING_SITUATION_6 = /*$$(*/
|
||||||
|
"You have to enter a prefix for automatic employee account creation in accounting application parameters of company %s" /*)*/;
|
||||||
|
static final String ACCOUNTING_SITUATION_7 = /*$$(*/
|
||||||
|
"You have to select a sequence for automatic employee account creation in accounting application parameters of company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Mail service */
|
||||||
|
static final String MAIL_1 = /*$$(*/
|
||||||
|
"%s : Please define an email template for cash register (company: %s)" /*)*/;
|
||||||
|
|
||||||
|
/** Account clearance service and controller */
|
||||||
|
static final String ACCOUNT_CLEARANCE_1 = /*$$(*/
|
||||||
|
"%s : You must configure account informations for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String ACCOUNT_CLEARANCE_2 = /*$$(*/
|
||||||
|
"%s : You must configure a financial account for then company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CLEARANCE_3 = /*$$(*/
|
||||||
|
"%s : You must configure a tax standard rate for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CLEARANCE_4 = /*$$(*/
|
||||||
|
"%s : You must configure account clearance for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CLEARANCE_5 = /*$$(*/
|
||||||
|
"%s : You must configure a clearance sequence of the overpayments for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CLEARANCE_6 = /*$$(*/
|
||||||
|
"%s : You must configure an overpayment account clearance journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CLEARANCE_7 = /*$$(*/ "Move lines generated" /*)*/;
|
||||||
|
|
||||||
|
/** Account customer service */
|
||||||
|
static final String ACCOUNT_CUSTOMER_1 = /*$$(*/
|
||||||
|
"%s : A customer account is missing for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String ACCOUNT_CUSTOMER_2 = /*$$(*/
|
||||||
|
"%s : A supplier account is missing for the company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Check rejection service */
|
||||||
|
static final String CHECK_REJECTION_1 = /*$$(*/
|
||||||
|
"%s : You must configure a cheque rejection sequence for the company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Irrecoverable service and controller */
|
||||||
|
static final String IRRECOVERABLE_1 = /*$$(*/ "Timetable line %s" /*)*/;
|
||||||
|
|
||||||
|
static final String IRRECOVERABLE_2 = /*$$(*/
|
||||||
|
"%s : Error generated on invoice creation shift to irrecoverable %s" /*)*/;
|
||||||
|
static final String IRRECOVERABLE_3 = /*$$(*/
|
||||||
|
"%s : The invoice %s has no accounting document whose the remainder to be paid is positive" /*)*/;
|
||||||
|
static final String IRRECOVERABLE_4 = /*$$(*/
|
||||||
|
"%s : You must configure shit to irrecoverable sequence for the company %s" /*)*/;
|
||||||
|
static final String IRRECOVERABLE_5 = /*$$(*/ "Treatment finished" /*)*/;
|
||||||
|
static final String IRRECOVERABLE_6 = /*$$(*/ "Anomalies generated" /*)*/;
|
||||||
|
static final String IRRECOVERABLE_7 = /*$$(*/ "You must select a printing type" /*)*/;
|
||||||
|
|
||||||
|
/** Journal service */
|
||||||
|
static final String JOURNAL_1 = /*$$(*/ "Invoice type missing on invoice %s" /*)*/;
|
||||||
|
|
||||||
|
/** Move line export service */
|
||||||
|
static final String MOVE_LINE_EXPORT_1 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a sale interface sequence for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String MOVE_LINE_EXPORT_2 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a credit note interface sequence for the company %s" /*)*/;
|
||||||
|
static final String MOVE_LINE_EXPORT_3 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a treasury interface sequence for the company %s" /*)*/;
|
||||||
|
static final String MOVE_LINE_EXPORT_4 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a purchase interface sequence for the company %s" /*)*/;
|
||||||
|
static final String MOVE_LINE_EXPORT_YEAR_OR_PERIOD_OR_DATE_IS_NULL = /*$$(*/
|
||||||
|
"Year or period or date is null, you must set a period." /*)*/;
|
||||||
|
|
||||||
|
/** Accounting report service and controller */
|
||||||
|
static final String ACCOUNTING_REPORT_1 = /*$$(*/
|
||||||
|
"%s : Error : You must configure an account reporting sequence for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String ACCOUNTING_REPORT_2 = /*$$(*/
|
||||||
|
"%s : Error : You must configure an account export sequence for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNTING_REPORT_3 = /*$$(*/ "Move lines recovered" /*)*/;
|
||||||
|
static final String ACCOUNTING_REPORT_4 = /*$$(*/ "You must select an export type" /*)*/;
|
||||||
|
static final String ACCOUNTING_REPORT_6 = /*$$(*/ "Moves exported" /*)*/;
|
||||||
|
static final String ACCOUNTING_REPORT_UNKNOWN_ACCOUNTING_REPORT_TYPE = /*$$(*/
|
||||||
|
"Unknown accounting report type: %d" /*)*/;
|
||||||
|
static final String ACCOUNTING_REPORT_ANALYTIC_REPORT = /*$$(*/
|
||||||
|
"%s : Error : You must configure an analytic report sequence for the company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Move line service */
|
||||||
|
static final String MOVE_LINE_1 = /*$$(*/ "Partner is missing on the invoice %s" /*)*/;
|
||||||
|
|
||||||
|
static final String MOVE_LINE_2 = /*$$(*/ "Partner account missing on the invoice %s" /*)*/;
|
||||||
|
static final String MOVE_LINE_4 = /*$$(*/
|
||||||
|
"Account missing on configuration for line : %s (company : %s)" /*)*/;
|
||||||
|
static final String MOVE_LINE_5 = /*$$(*/
|
||||||
|
"Analytic account %s associated to sales account for the product %s is not configured : (company : %s)" /*)*/;
|
||||||
|
static final String MOVE_LINE_6 = /*$$(*/
|
||||||
|
"Account missing on the tax line : %s (company : %s)" /*)*/;
|
||||||
|
static final String ANALYTIC_DISTRIBUTION_MISSING = /*$$(*/
|
||||||
|
"Analytic distribution is missing on configuration for line : %s (company : %s)" /*)*/;
|
||||||
|
static final String MOVE_LINE_7 = /*$$(*/
|
||||||
|
"The accounting move line on the account %s can't have an amount equals to zero" /*)*/;
|
||||||
|
|
||||||
|
/** Move service */
|
||||||
|
static final String MOVE_1 = /*$$(*/ "Invoice type missing on invoice %s" /*)*/;
|
||||||
|
|
||||||
|
static final String MOVE_2 = /*$$(*/ "You must select a journal for the move %s" /*)*/;
|
||||||
|
static final String MOVE_3 = /*$$(*/ "You must select a company for the move %s" /*)*/;
|
||||||
|
static final String MOVE_4 = /*$$(*/ "You must select a period for the move %s" /*)*/;
|
||||||
|
static final String MOVE_5 = /*$$(*/
|
||||||
|
"Journal %s does not have any account move sequence configured" /*)*/;
|
||||||
|
static final String MOVE_6 = /*$$(*/ "Move account sens %s can't be determined" /*)*/;
|
||||||
|
static final String MOVE_7 = /*$$(*/
|
||||||
|
"Account move %s has a total debit different than total credit : %s <> %s" /*)*/;
|
||||||
|
static final String MOVE_8 = /*$$(*/ "The move %s cannot be empty" /*)*/;
|
||||||
|
static final String MOVE_9 = /*$$(*/
|
||||||
|
"Tax is mandatory for the account %s on the move line %s" /*)*/;
|
||||||
|
static final String MOVE_10 = /*$$(*/
|
||||||
|
"Analytic distribution template is mandatory for the account %s on the move line %s." /*)*/;
|
||||||
|
static final String MOVE_11 = /*$$(*/
|
||||||
|
"An analytic distribution is set in move line %s but the account used do not allow analytic distribution" /*)*/;
|
||||||
|
static final String MOVE_VALIDATION_FISCAL_PERIOD_CLOSED = /*$$(*/
|
||||||
|
"Accounting move can not be validated because its fiscal period is closed." /*)*/;
|
||||||
|
|
||||||
|
/** Payment schedule export service */
|
||||||
|
static final String PAYMENT_SCHEDULE_1 = /*$$(*/
|
||||||
|
"%s : You must configure a RIB for payment timetable %s" /*)*/;
|
||||||
|
|
||||||
|
static final String PAYMENT_SCHEDULE_2 = /*$$(*/
|
||||||
|
"%s : You must configure a RIB for the partner %s" /*)*/;
|
||||||
|
static final String PAYMENT_SCHEDULE_3 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a direct debit date for the %s batch configuration" /*)*/;
|
||||||
|
static final String PAYMENT_SCHEDULE_4 = /*$$(*/
|
||||||
|
"%s : You must configure a direct debit reject sequence\n for the company %s for the journal %s" /*)*/;
|
||||||
|
static final String PAYMENT_SCHEDULE_5 = /*$$(*/
|
||||||
|
"You must configure a timetable sequence for the company %s" /*)*/;
|
||||||
|
static final String PAYMENT_SCHEDULE_6 = /*$$(*/
|
||||||
|
"%s : Error : You must, at first, create timetable lines for the timetable %s" /*)*/;
|
||||||
|
static final String PAYMENT_SCHEDULE_LINE_AMOUNT_MISMATCH = /*$$(*/
|
||||||
|
"The sum of line amounts (%s) must match the amount of the payment schedule (%s)." /*)*/;
|
||||||
|
|
||||||
|
/** Reconcile service */
|
||||||
|
static final String RECONCILE_1 = /*$$(*/
|
||||||
|
"%s : Reconciliation : You must fill concerned moves lines." /*)*/;
|
||||||
|
|
||||||
|
static final String RECONCILE_2 = /*$$(*/
|
||||||
|
"%s : Reconciliation : Move line accounts are not compatible." /*)*/;
|
||||||
|
static final String RECONCILE_3 = /*$$(*/
|
||||||
|
"(Debit %s account %s amount %s - Credit %s account %s amount %s)" /*)*/;
|
||||||
|
static final String RECONCILE_4 = /*$$(*/
|
||||||
|
"%s : Reconciliation %s: Reconciliated amount must be different than zero. (Debit %s account %s - Credit %s account %s)" /*)*/;
|
||||||
|
static final String RECONCILE_5 = /*$$(*/
|
||||||
|
"%s : Reconciliation %s: Reconciliated amount (%s) must be lower or equal to remaining amount to reconciliate from moves lines." /*)*/;
|
||||||
|
static final String RECONCILE_6 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a reconciliation sequence for the company %s" /*)*/;
|
||||||
|
static final String RECONCILE_7 = /*$$(*/
|
||||||
|
"Reconciliation : Selected moves lines must concern the same company. Reconcile : %s company \n Debit move line : %s company \n Credit move line : %s company" /*)*/;
|
||||||
|
static final String RECONCILE_CAN_NOT_BE_REMOVE = /*$$(*/
|
||||||
|
"The reconcile %s cannot be removed, please select draft reconcile(s)" /*)*/;
|
||||||
|
|
||||||
|
/** Reimbursement service and controller */
|
||||||
|
static final String REIMBURSEMENT_1 = /*$$(*/
|
||||||
|
"%s : You must configure a reimbursement sequence for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String REIMBURSEMENT_2 = /*$$(*/
|
||||||
|
"Export reimbursement folder (SEPA format) has not been configured for the company %s." /*)*/;
|
||||||
|
static final String REIMBURSEMENT_3 = /*$$(*/
|
||||||
|
"No reimbursement found for the ref %s and the company %s." /*)*/;
|
||||||
|
static final String REIMBURSEMENT_4 = /*$$(*/ "You must configure a RIB." /*)*/;
|
||||||
|
|
||||||
|
/** Year service */
|
||||||
|
static final String YEAR_1 = /*$$(*/
|
||||||
|
"%s : You must configure a company for the fiscal year %s" /*)*/;
|
||||||
|
|
||||||
|
/** Batch Account customer */
|
||||||
|
static final String BATCH_ACCOUNT_1 = /*$$(*/ "Accounting situation %s" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_ACCOUNT_2 = /*$$(*/
|
||||||
|
"Contact's account balances determination's reporting :" /*)*/;
|
||||||
|
static final String BATCH_ACCOUNT_3 = /*$$(*/ "* %s Account(s) situation(s) treated" /*)*/;
|
||||||
|
static final String BATCH_ACCOUNT_4 = /*$$(*/
|
||||||
|
"Account balances of %s accounting situation has not been updated, you must run the contact account batch update." /*)*/;
|
||||||
|
static final String BATCH_ACCOUNT_5 = /*$$(*/
|
||||||
|
"Account balances from all accounts situations (%s) has been updated." /*)*/;
|
||||||
|
|
||||||
|
/** Batch doubtful customer */
|
||||||
|
static final String BATCH_DOUBTFUL_1 = /*$$(*/
|
||||||
|
"Doubtful account's determination's reporting" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_DOUBTFUL_2 = /*$$(*/ "* %s Invoice(s) treated" /*)*/;
|
||||||
|
|
||||||
|
/** Batch move line export */
|
||||||
|
static final String BATCH_MOVELINE_EXPORT_1 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a company for the batch configurator %s" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_MOVELINE_EXPORT_2 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a due date for the batch configurator %s" /*)*/;
|
||||||
|
static final String BATCH_MOVELINE_EXPORT_3 = /*$$(*/
|
||||||
|
"%s : Error : You must configure an export type for the batch configurator %s" /*)*/;
|
||||||
|
static final String BATCH_MOVELINE_EXPORT_4 = /*$$(*/ "Moves export batch's reporting :" /*)*/;
|
||||||
|
static final String BATCH_MOVELINE_EXPORT_5 = /*$$(*/ "Moves Lines (Moves) exported" /*)*/;
|
||||||
|
|
||||||
|
/** Batch payment schedule import/export */
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_1 = /*$$(*/
|
||||||
|
"Unknowned data type for the treatment %s" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_2 = /*$$(*/ "Direct debit's export batch %s" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_3 = /*$$(*/ "Due date's direct debit %s" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_4 = /*$$(*/
|
||||||
|
"Export reporting to invoices direct debits :" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_5 = /*$$(*/ "Invoice(s) direct debit(s) treated" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_6 = /*$$(*/
|
||||||
|
"Export reporting to monthly direct debits :" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_7 = /*$$(*/ "Monthly direct debit(s) treated" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_8 = /*$$(*/
|
||||||
|
"%s : No timetable nor invoice found for the direct debit number : %s" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_9 = /*$$(*/ "Reject %s" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_10 = /*$$(*/
|
||||||
|
"Timetable's reject move's creation %s" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_11 = /*$$(*/
|
||||||
|
"Invoice's reject move's creation %s" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_12 = /*$$(*/
|
||||||
|
"Reporting to direct debit reject's import :" /*)*/;
|
||||||
|
static final String BATCH_PAYMENT_SCHEDULE_13 = /*$$(*/ "Direct debit(s) rejected" /*)*/;
|
||||||
|
|
||||||
|
/** Batch reimbursement export/import */
|
||||||
|
static final String BATCH_REIMBURSEMENT_1 = /*$$(*/
|
||||||
|
"Bug(Anomaly) generated during SEPA export - Batch %s" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_REIMBURSEMENT_2 = /*$$(*/ "Reporting to reimbursement creation :" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_3 = /*$$(*/ "Reimbursement(s) created" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_4 = /*$$(*/ "Reporting to reimbursement's export :" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_5 = /*$$(*/ "Reimbursement(s) treated" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_6 = /*$$(*/ "Reimbursement's import's batch %s" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_7 = /*$$(*/ "Reimbursement reject %s" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_8 = /*$$(*/
|
||||||
|
"Reporting to reimbursement reject's import :" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_9 = /*$$(*/ "Reimbursement(s) rejected" /*)*/;
|
||||||
|
static final String BATCH_REIMBURSEMENT_10 = /*$$(*/ "Total Amount" /*)*/;
|
||||||
|
|
||||||
|
/** Batch debt recovery */
|
||||||
|
static final String BATCH_DEBT_RECOVERY_1 = /*$$(*/ "Debt recovery's reporting :" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_DEBT_RECOVERY_2 = /*$$(*/ "Partner(s) treated" /*)*/;
|
||||||
|
|
||||||
|
/** Batch credit transfer */
|
||||||
|
static final String BATCH_CREDIT_TRANSFER_REPORT_TITLE = /*$$(*/
|
||||||
|
"Report for credit transfer batch:" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_CREDIT_TRANSFER_INVOICE_DONE_SINGULAR = /*$$(*/
|
||||||
|
"%d invoice treated successfully," /*)*/;
|
||||||
|
static final String BATCH_CREDIT_TRANSFER_INVOICE_DONE_PLURAL = /*$$(*/
|
||||||
|
"%d invoices treated successfully," /*)*/;
|
||||||
|
static final String BATCH_CREDIT_TRANSFER_REIMBURSEMENT_DONE_SINGULAR = /*$$(*/
|
||||||
|
"%d reimbursement created successfully," /*)*/;
|
||||||
|
static final String BATCH_CREDIT_TRANSFER_REIMBURSEMENT_DONE_PLURAL = /*$$(*/
|
||||||
|
"%d reimbursements created successfully," /*)*/;
|
||||||
|
static final String BATCH_CREDIT_TRANSFER_ANOMALY_SINGULAR = /*$$(*/ "%d anomaly." /*)*/;
|
||||||
|
static final String BATCH_CREDIT_TRANSFER_ANOMALY_PLURAL = /*$$(*/ "%d anomalies." /*)*/;
|
||||||
|
|
||||||
|
/** Batch strategy */
|
||||||
|
static final String BATCH_STRATEGY_1 = /*$$(*/
|
||||||
|
"%s : You must configure a RIB for batch's configurator %s" /*)*/;
|
||||||
|
|
||||||
|
/** Batch realize fixed asset lines */
|
||||||
|
static final String BATCH_REALIZED_FIXED_ASSET_LINE = /*$$(*/ "Realized fixed asset lines" /*)*/;
|
||||||
|
|
||||||
|
/** Batch close / open the year account */
|
||||||
|
static final String BATCH_CLOSE_OPEN_ANNUAL_ACCOUNT_REPORT_TITLE = /*$$(*/
|
||||||
|
"Report for close/open annual accounts batch:" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_CLOSE_OPEN_ANNUAL_ACCOUNT_DONE_SINGULAR = /*$$(*/
|
||||||
|
"%d account treated successfully," /*)*/;
|
||||||
|
static final String BATCH_CLOSE_OPEN_ANNUAL_ACCOUNT_DONE_PLURAL = /*$$(*/
|
||||||
|
"%d accounts treated successfully," /*)*/;
|
||||||
|
|
||||||
|
/** Cfonb export service */
|
||||||
|
static final String CFONB_EXPORT_1 = /*$$(*/
|
||||||
|
"You must configure a RIB for the reimbursement" /*)*/;
|
||||||
|
|
||||||
|
static final String CFONB_EXPORT_2 = /*$$(*/
|
||||||
|
"%s : Error detected during CFONB file's writing : %s" /*)*/;
|
||||||
|
static final String CFONB_EXPORT_3 = /*$$(*/
|
||||||
|
"%s : You must configure a Sort Code for the RIB %s of third-payer %s" /*)*/;
|
||||||
|
static final String CFONB_EXPORT_4 = /*$$(*/
|
||||||
|
"%s : You must configure a number's account for the RIB %s of third-payer %s" /*)*/;
|
||||||
|
static final String CFONB_EXPORT_5 = /*$$(*/
|
||||||
|
"%s : You must configure a Bank Code for the RIB %s of third-payer %s" /*)*/;
|
||||||
|
static final String CFONB_EXPORT_6 = /*$$(*/
|
||||||
|
"%s : You must configure a Bank Address for the RIB %s of third-payer %s" /*)*/;
|
||||||
|
|
||||||
|
/** Cfonb import service */
|
||||||
|
static final String CFONB_IMPORT_1 = /*$$(*/
|
||||||
|
"%s : You must configure a reject/return reason's code's list relating to Card cashing, Direct debit and TIP in general configuration" /*)*/;
|
||||||
|
|
||||||
|
static final String CFONB_IMPORT_2 = /*$$(*/
|
||||||
|
"%s : A header record is missing in the file %s" /*)*/;
|
||||||
|
static final String CFONB_IMPORT_3 = /*$$(*/
|
||||||
|
"%s : One or several detail records are missing in the file %s" /*)*/;
|
||||||
|
static final String CFONB_IMPORT_4 = /*$$(*/ "%s : A record is missing in the file %s" /*)*/;
|
||||||
|
static final String CFONB_IMPORT_5 = /*$$(*/
|
||||||
|
"%s : The total amount for the following record isn't correct (file %s) :\n %s" /*)*/;
|
||||||
|
static final String CFONB_IMPORT_6 = /*$$(*/
|
||||||
|
"%s : No payment mode found for the code %s and the company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Cfonb tool service */
|
||||||
|
static final String CFONB_TOOL_NB_OF_CHAR_PER_LINE = /*$$(*/
|
||||||
|
"The record is not %s characters" /*)*/;
|
||||||
|
|
||||||
|
static final String CFONB_TOOL_EMPTY_ZONE = /*$$(*/ "Zone %s is empty" /*)*/;
|
||||||
|
static final String CFONB_TOOL_DIGITAL_ZONE_NOT_CORRECT = /*$$(*/
|
||||||
|
"Zone %s (%s) must be of the numeric type" /*)*/;
|
||||||
|
static final String CFONB_TOOL_1 = /*$$(*/
|
||||||
|
"%s : Anomaly detected (value isn't numeric : %s) for sender" /*)*/;
|
||||||
|
static final String CFONB_TOOL_2 = /*$$(*/
|
||||||
|
"%s : Anomaly detected (value isn't numeric : %s) for the receiver" /*)*/;
|
||||||
|
static final String CFONB_TOOL_3 = /*$$(*/
|
||||||
|
"%s : Anomaly detected (value isn't numeric : %s) for the total" /*)*/;
|
||||||
|
static final String CFONB_TOOL_4 = /*$$(*/
|
||||||
|
"%s : Anomaly detected (the record doesn't have %s characters : %s) for the record %s, company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String COMPANY_CURRENCY = /*$$(*/
|
||||||
|
"%s : Please, configure a currency for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String ACCOUNT_CONFIG_1 = /*$$(*/
|
||||||
|
"%s : You must configure account's informations for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_2 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB format reimbursement's export's folder for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_3 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB format direct debit's export's folder for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_4 = /*$$(*/
|
||||||
|
"%s : You must configure a TIP and cheque TIP payment's import path for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_5 = /*$$(*/
|
||||||
|
"%s : You must configure a TIP and cheque TIP temporary import path for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_6 = /*$$(*/
|
||||||
|
"%s : You must configure a TIP and cheque TIP payment rejects path for the import file for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_7 = /*$$(*/
|
||||||
|
"%s : You must configure a TIP and cheque TIP temporary path for the payment reject's file for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_8 = /*$$(*/
|
||||||
|
"%s : You must configure a path for the reject's file for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_9 = /*$$(*/
|
||||||
|
"%s : You must configure a path for the temporary reject's file for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_10 = /*$$(*/
|
||||||
|
"%s : You must configure a path for the reimbursements rejects import's file for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_11 = /*$$(*/
|
||||||
|
"%s : You must configure a path for the reimbursement rejects import's temporary file for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_12 = /*$$(*/
|
||||||
|
"%s : You must configure a rejects journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_13 = /*$$(*/
|
||||||
|
"%s : You must configure an irrevocable journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_14 = /*$$(*/
|
||||||
|
"%s : You must configure a Supplier purchase journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_15 = /*$$(*/
|
||||||
|
"%s : You must configure a Supplier credit note journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_16 = /*$$(*/
|
||||||
|
"%s : You must configure a Sales journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_17 = /*$$(*/
|
||||||
|
"%s : You must configure a Customer credit note journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_18 = /*$$(*/
|
||||||
|
"%s : You must configure a Misc. Operation journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_19 = /*$$(*/
|
||||||
|
"%s : You must configure a Reimbursement journal for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_20 = /*$$(*/
|
||||||
|
"%s : You must configure a Sales journal type for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_21 = /*$$(*/
|
||||||
|
"%s : You must configure a Credit note journal type for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_22 = /*$$(*/
|
||||||
|
"%s : You must configure a Cash journal type for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_23 = /*$$(*/
|
||||||
|
"%s : You must configure a Purchase journal type for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_24 = /*$$(*/
|
||||||
|
"%s : You must configure an irrevocable doubtful account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_25 = /*$$(*/
|
||||||
|
"%s : You must configure a customer account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_26 = /*$$(*/
|
||||||
|
"%s : You must configure a supplier account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_27 = /*$$(*/
|
||||||
|
"%s : You must configure a cash difference account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_28 = /*$$(*/
|
||||||
|
"%s : You must configure a reimbursement account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_29 = /*$$(*/
|
||||||
|
"%s : You must configure a doubtful customer account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_30 = /*$$(*/
|
||||||
|
"%s : You must configure a direct debit payment mode for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_31 = /*$$(*/
|
||||||
|
"%s : You must configure a payment mode after reject for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_32 = /*$$(*/
|
||||||
|
"%s : You must configure a shift to irrecoverable's reason for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_34 = /*$$(*/
|
||||||
|
"%s : You must configure a reject import letter template for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_35 = /*$$(*/
|
||||||
|
"%s : You must configure a shifting reason (debt more than six months) for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_36 = /*$$(*/
|
||||||
|
"%s : You must configure a shifting reason (debt more than three months) for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_37 = /*$$(*/
|
||||||
|
"%s : You must configure a debt recovery tab for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_38 = /*$$(*/
|
||||||
|
"%s : You must configure an advance payment account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_39 = /*$$(*/
|
||||||
|
"%s : You must configure a file name for the export of move file for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_40 = /*$$(*/
|
||||||
|
"%s : You must configure an employee account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_41 = /*$$(*/
|
||||||
|
"%s : You must configure a factor credit account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_42 = /*$$(*/
|
||||||
|
"%s : You must configure a factor debit account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_43 = /*$$(*/
|
||||||
|
"%s : You must configure a year opening account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_44 = /*$$(*/
|
||||||
|
"%s : You must configure a year closure account for the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_45 = /*$$(*/
|
||||||
|
"%s : You must configure a reported balance journal for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String ACCOUNT_CONFIG_SEQUENCE_1 = /*$$(*/
|
||||||
|
"%s : Please, configure a sequence for the customer invoices and the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_SEQUENCE_2 = /*$$(*/
|
||||||
|
"%s : Please, configure a sequence for the customer refunds and the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_SEQUENCE_3 = /*$$(*/
|
||||||
|
"%s : Please, configure a sequence for the supplier invoices and the company %s" /*)*/;
|
||||||
|
static final String ACCOUNT_CONFIG_SEQUENCE_4 = /*$$(*/
|
||||||
|
"%s : Please, configure a sequence for the supplier refunds and the company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Cfonb config service */
|
||||||
|
static final String CFONB_CONFIG_1 = /*$$(*/
|
||||||
|
"%s : You must configure CFONB for the company %s" /*)*/;
|
||||||
|
|
||||||
|
static final String CFONB_CONFIG_2 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB sender code register for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_3 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB sender's number for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_4 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB sender's name/corporate name for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_5 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB receiver code register for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_6 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB total code register for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_7 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB internet payment code for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_8 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB direct debit code for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_9 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB header code register for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_10 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB detail code register for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_11 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB code register end for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_12 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB rejected direct debit code for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_13 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB unpaid direct debit code fir the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_14 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB unpaid TIP code for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_15 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB TIP and cheque TIP code for the company %s" /*)*/;
|
||||||
|
static final String CFONB_CONFIG_16 = /*$$(*/
|
||||||
|
"%s : You must configure a CFONB TIP code for the company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Payer quality service */
|
||||||
|
static final String PAYER_QUALITY_1 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a weight table in general configuration" /*)*/;
|
||||||
|
|
||||||
|
/** Debt recovery action service */
|
||||||
|
static final String DEBT_RECOVERY_ACTION_1 = /*$$(*/ "Debt recovery method missing." /*)*/;
|
||||||
|
|
||||||
|
static final String DEBT_RECOVERY_ACTION_2 = /*$$(*/ "Debt recovery line missing." /*)*/;
|
||||||
|
static final String DEBT_RECOVERY_ACTION_3 = /*$$(*/
|
||||||
|
"%s : Letter template missing for debt recovery matrix %s (Partner %s, Level %s)." /*)*/;
|
||||||
|
static final String DEBT_RECOVERY_ACTION_4 = /*$$(*/
|
||||||
|
"Email is not sent. Please check email account configuration." /*)*/;
|
||||||
|
|
||||||
|
/** Debt recovery service */
|
||||||
|
static final String DEBT_RECOVERY_1 = /*$$(*/ "There's no accounting situation." /*)*/;
|
||||||
|
|
||||||
|
static final String DEBT_RECOVERY_2 = /*$$(*/ "Reference date undefined." /*)*/;
|
||||||
|
static final String DEBT_RECOVERY_3 = /*$$(*/
|
||||||
|
"Debt recovery method missing for the configuration." /*)*/;
|
||||||
|
static final String DEBT_RECOVERY_4 = /*$$(*/ "Debt recovery level waiting for approval." /*)*/;
|
||||||
|
static final String DEBT_RECOVERY_DEBT_RECOVERY_LEVEL_NOT_FOUND = /*$$(*/
|
||||||
|
"Debt recovery method line not found" /*)*/;
|
||||||
|
|
||||||
|
/** Debt recovery session service */
|
||||||
|
static final String DEBT_RECOVERY_SESSION_1 = /*$$(*/ "Debt recovery method line missing." /*)*/;
|
||||||
|
|
||||||
|
/** Invoice batch service */
|
||||||
|
static final String INVOICE_BATCH_1 = /*$$(*/ "State %s unknown for treatment %s" /*)*/;
|
||||||
|
|
||||||
|
/** Invoice generator */
|
||||||
|
static final String INVOICE_GENERATOR_1 = /*$$(*/ "%s : Invoice's type is not filled %s" /*)*/;
|
||||||
|
|
||||||
|
static final String INVOICE_GENERATOR_2 = /*$$(*/ "%s : There's no partner selected" /*)*/;
|
||||||
|
static final String INVOICE_GENERATOR_3 = /*$$(*/ "%s : Payment condition missing" /*)*/;
|
||||||
|
static final String INVOICE_GENERATOR_4 = /*$$(*/ "%s : Payment mode missing" /*)*/;
|
||||||
|
static final String INVOICE_GENERATOR_5 = /*$$(*/ "%s : Invoicing address missing" /*)*/;
|
||||||
|
static final String INVOICE_GENERATOR_6 = /*$$(*/ "%s : Currency missing" /*)*/;
|
||||||
|
|
||||||
|
/** Merge Invoice */
|
||||||
|
public static final String INVOICE_MERGE_ERROR_CURRENCY = /*$$(*/
|
||||||
|
"The currency is required and must be the same for all invoices" /*)*/;
|
||||||
|
|
||||||
|
public static final String INVOICE_MERGE_ERROR_PARTNER = /*$$(*/
|
||||||
|
"The partner is required and must be the same for all invoices" /*)*/;
|
||||||
|
public static final String INVOICE_MERGE_ERROR_COMPANY = /*$$(*/
|
||||||
|
"The company is required and must be the same for all invoices" /*)*/;
|
||||||
|
public static final String INVOICE_MERGE_ERROR_SALEORDER = /*$$(*/
|
||||||
|
"The sale order must be the same for all invoices" /*)*/;
|
||||||
|
public static final String INVOICE_MERGE_ERROR_PROJECT = /*$$(*/
|
||||||
|
"The project must be the same for all invoices" /*)*/;
|
||||||
|
public static final String INVOICE_MASS_PAYMENT_ERROR_PFP_LITIGATION = /*$$(*/
|
||||||
|
"Their is at least one invoice selected that it is not validated to pay" /*)*/;
|
||||||
|
|
||||||
|
/** Invoice line generator */
|
||||||
|
static final String INVOICE_LINE_GENERATOR_1 = /*$$(*/
|
||||||
|
"You must select a currency for partner %s (%s)" /*)*/;
|
||||||
|
|
||||||
|
static final String INVOICE_LINE_GENERATOR_2 = /*$$(*/
|
||||||
|
"You must select a currency for company %s" /*)*/;
|
||||||
|
|
||||||
|
public static final String INVOICE_LINE_ERROR_FIXED_ASSET_CATEGORY = /*$$(*/
|
||||||
|
"Fixed asset category is missing on invoice line for product %s" /*)*/;
|
||||||
|
|
||||||
|
/** Batch validation */
|
||||||
|
static final String BATCH_VALIDATION_1 = /*$$(*/ "Invoice validation's reporting :" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_VALIDATION_2 = /*$$(*/ "Invoice(s) validated" /*)*/;
|
||||||
|
|
||||||
|
/** Batch ventilation */
|
||||||
|
static final String BATCH_VENTILATION_1 = /*$$(*/ "Invoice ventilation's reporting :" /*)*/;
|
||||||
|
|
||||||
|
static final String BATCH_VENTILATION_2 = /*$$(*/ "Invoice(s) ventilated" /*)*/;
|
||||||
|
|
||||||
|
/** Refund invoice */
|
||||||
|
static final String REFUND_INVOICE_1 = /*$$(*/
|
||||||
|
"%s : Payment mode must be filled either in the partner or in the company configuration." /*)*/;
|
||||||
|
|
||||||
|
/** Validate state */
|
||||||
|
static final String INVOICE_VALIDATE_1 = /*$$(*/
|
||||||
|
"The payment mode is not in adequacy with the invoice type" /*)*/;
|
||||||
|
|
||||||
|
static final String INVOICE_VALIDATE_BLOCKING = /*$$(*/
|
||||||
|
"The partner is blocked for invoicing." /*)*/;
|
||||||
|
|
||||||
|
/** Cancel state */
|
||||||
|
static final String MOVE_CANCEL_1 = /*$$(*/
|
||||||
|
"Move should be unreconcile before to cancel the invoice" /*)*/;
|
||||||
|
|
||||||
|
static final String MOVE_CANCEL_2 = /*$$(*/
|
||||||
|
"Move is ventilated on a closed period, and can't be canceled" /*)*/;
|
||||||
|
static final String MOVE_CANCEL_3 = /*$$(*/
|
||||||
|
"So many accounting operations are used on this move, so move can't be canceled" /*)*/;
|
||||||
|
|
||||||
|
static final String INVOICE_CANCEL_1 = /*$$(*/
|
||||||
|
"Invoice is passed in doubfult debit, and can't be canceled" /*)*/;
|
||||||
|
|
||||||
|
static final String INVOICE_PAYMENT_CANCEL = /*$$(*/
|
||||||
|
"The bank order linked to this invoice payment has already been carried out/rejected, and thus can't be canceled" /*)*/;
|
||||||
|
|
||||||
|
/** Ventilate state */
|
||||||
|
static final String VENTILATE_STATE_1 = /*$$(*/
|
||||||
|
"Invoice's or credit note's date can't be previous last invoice ventilated's date" /*)*/;
|
||||||
|
|
||||||
|
static final String VENTILATE_STATE_2 = /*$$(*/
|
||||||
|
"Invoice's or credit note's date can't be previous last invoice ventilated on month's date" /*)*/;
|
||||||
|
static final String VENTILATE_STATE_3 = /*$$(*/
|
||||||
|
"Invoice's or credit note's date can't be previous last invoice ventilated on year's date" /*)*/;
|
||||||
|
static final String VENTILATE_STATE_4 = /*$$(*/
|
||||||
|
"Company %s does not have any invoice's nor credit note's sequence" /*)*/;
|
||||||
|
static final String VENTILATE_STATE_5 = /*$$(*/
|
||||||
|
"The partner account can not be determined. Please set up the partner account on the invoice or configure the partner's accounting situation." /*)*/;
|
||||||
|
static final String VENTILATE_STATE_6 = /*$$(*/
|
||||||
|
"The account of a product could not be determined or is not filled. Please fill the missing account on invoice line %s" /*)*/;
|
||||||
|
static final String VENTILATE_STATE_7 = /*$$(*/
|
||||||
|
"An analytic distribution is set in product but the account used do not allow analytic distribution" /*)*/;
|
||||||
|
|
||||||
|
static final String VENTILATE_STATE_FUTURE_DATE = /*$$(*/
|
||||||
|
"Invoice date can't be in the future." /*)*/;
|
||||||
|
|
||||||
|
static final String VENTILATE_STATE_FUTURE_ORIGIN_DATE = /*$$(*/
|
||||||
|
"Invoice date of origin can't be in the future." /*)*/;
|
||||||
|
|
||||||
|
static final String VENTILATE_STATE_MISSING_ORIGIN_DATE = /*$$(*/
|
||||||
|
"Origin date is missing on the invoice" /*)*/;
|
||||||
|
|
||||||
|
/** Workflow ventilation */
|
||||||
|
String AMOUNT_ADVANCE_PAYMENTS_TOO_HIGH = /*$$(*/
|
||||||
|
"Sum of advance payments amounts is higher than the total of this invoice." /*)*/;
|
||||||
|
|
||||||
|
static final String PAYMENT_AMOUNT_EXCEEDING = /*$$(*/
|
||||||
|
"%s : Caution - You can't pay for an amount higher than selected invoices" /*)*/;
|
||||||
|
|
||||||
|
/** Payment mode service */
|
||||||
|
static final String PAYMENT_MODE_1 = /*$$(*/ "Associated account not configured" /*)*/;
|
||||||
|
|
||||||
|
static final String PAYMENT_MODE_2 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a sequence for the company %s and a payment mode %s" /*)*/;
|
||||||
|
static final String PAYMENT_MODE_3 = /*$$(*/
|
||||||
|
"%s : Error : You must configure a journal for the company %s and a payment mode %s" /*)*/;
|
||||||
|
|
||||||
|
/** Payment voucher control service */
|
||||||
|
static final String PAYMENT_VOUCHER_CONTROL_PAID_AMOUNT = /*$$(*/
|
||||||
|
"%s : Payment voucher n° %s, the paid amount should be positive" /*)*/;
|
||||||
|
|
||||||
|
static final String PAYMENT_VOUCHER_CONTROL_1 = /*$$(*/
|
||||||
|
"%s : Caution, payment entry nb %s, total line's amount imputed is higher than customer's amount paid." /*)*/;
|
||||||
|
static final String PAYMENT_VOUCHER_CONTROL_2 = /*$$(*/ "%s : There's no line to pay." /*)*/;
|
||||||
|
static final String PAYMENT_VOUCHER_CONTROL_3 = /*$$(*/
|
||||||
|
"%s : You must add a journal and a treasury account into payment mode." /*)*/;
|
||||||
|
|
||||||
|
/** Payment voucher load service */
|
||||||
|
static final String PAYMENT_VOUCHER_LOAD_1 = /*$$(*/ "%s : You must add an amount paid." /*)*/;
|
||||||
|
|
||||||
|
/** Payment voucher sequence service */
|
||||||
|
static final String PAYMENT_VOUCHER_SEQUENCE_1 = /*$$(*/
|
||||||
|
"%s : You must configure a receipt number (Payment entry) for the company %s" /*)*/;
|
||||||
|
|
||||||
|
/** Payment voucher tool service */
|
||||||
|
static final String PAYMENT_VOUCHER_TOOL_1 = /*$$(*/
|
||||||
|
"Payment entry's type missing from payment entry %s" /*)*/;
|
||||||
|
|
||||||
|
/** Payment schedule line service */
|
||||||
|
String PAYMENT_SCHEDULE_LINE_NO_DIRECT_DEBIT_PAYMENT_MODE = /*$$(*/
|
||||||
|
"Missing direct debit payment mode in the company's account configuration" /*)*/;
|
||||||
|
|
||||||
|
/** Account chart controller */
|
||||||
|
static final String ACCOUNT_CHART_1 = /*$$(*/
|
||||||
|
"The chart of account has been loaded successfully" /*)*/;
|
||||||
|
|
||||||
|
static final String ACCOUNT_CHART_2 = /*$$(*/
|
||||||
|
"Error in account chart import please check the log" /*)*/;
|
||||||
|
static final String ACCOUNT_CHART_3 = /*$$(*/
|
||||||
|
"A chart or chart structure of accounts already exists, please delete the hierarchy between accounts in order to import a new chart." /*)*/;
|
||||||
|
|
||||||
|
/** Address controller */
|
||||||
|
static final String ADDRESS_1 = /*$$(*/ "Sales map" /*)*/;
|
||||||
|
|
||||||
|
static final String ADDRESS_2 = /*$$(*/ "Not implemented for OSM" /*)*/;
|
||||||
|
|
||||||
|
/** Invoice controller */
|
||||||
|
static final String INVOICE_1 = /*$$(*/ "Invoice canceled" /*)*/;
|
||||||
|
|
||||||
|
static final String INVOICE_2 = /*$$(*/ "Credit note created" /*)*/;
|
||||||
|
static final String INVOICE_3 = /*$$(*/ "Please select the invoice(s) to print." /*)*/;
|
||||||
|
static final String INVOICE_4 = /*$$(*/ "Refunds from invoice %s" /*)*/;
|
||||||
|
|
||||||
|
static final String INVOICE_NO_INVOICE_TO_PAY = /*$$(*/ "No invoice to pay" /*)*/;
|
||||||
|
|
||||||
|
/** Move template controller */
|
||||||
|
static final String MOVE_TEMPLATE_1 = /*$$(*/ "Template move is not balanced" /*)*/;
|
||||||
|
|
||||||
|
static final String MOVE_TEMPLATE_2 = /*$$(*/ "Error in move generation" /*)*/;
|
||||||
|
static final String MOVE_TEMPLATE_3 = /*$$(*/ "Generated moves" /*)*/;
|
||||||
|
static final String MOVE_TEMPLATE_4 = /*$$(*/ "Please fill input lines" /*)*/;
|
||||||
|
|
||||||
|
/** Budget service */
|
||||||
|
static final String BUDGET_1 = /*$$(*/ "Too much iterations." /*)*/;
|
||||||
|
|
||||||
|
static final String USER_PARTNER = /*$$(*/ "You must create a contact for user %s" /*)*/;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deposit slip
|
||||||
|
*/
|
||||||
|
static final String DEPOSIT_SLIP_MISSING_SEQUENCE = /*$$(*/
|
||||||
|
"Missing deposit slip sequence for company %s" /*)*/;
|
||||||
|
static final String DEPOSIT_SLIP_CANNOT_DELETE = /*$$(*/
|
||||||
|
"You cannot delete this deposit slip." /*)*/;
|
||||||
|
static final String DEPOSIT_SLIP_ALREADY_PUBLISHED = /*$$(*/
|
||||||
|
"The deposit slip has already been published." /*)*/;
|
||||||
|
static final String DEPOSIT_SLIP_UNSUPPORTED_PAYMENT_MODE_TYPE = /*$$(*/
|
||||||
|
"Unsupported payment mode type" /*)*/;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Partner
|
||||||
|
*/
|
||||||
|
String PARTNER_BANK_DETAILS_MISSING = /*$$(*/ "Bank details are missing for partner %s." /*)*/;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invoice printing
|
||||||
|
*/
|
||||||
|
String INVOICE_MISSING_PRINTING_SETTINGS = /*$$(*/
|
||||||
|
"Please fill printing settings on invoice %s." /*)*/;
|
||||||
|
String INVOICES_MISSING_PRINTING_SETTINGS = /*$$(*/
|
||||||
|
"Please fill printing settings on following invoices: %s" /*)*/;
|
||||||
|
String INVOICE_PRINTING_IO_ERROR = /*$$(*/ "Error on uploading printed invoice:" /*)*/;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reconcile Group
|
||||||
|
*/
|
||||||
|
String RECONCILE_GROUP_VALIDATION_NO_LINES = /*$$(*/
|
||||||
|
"The reconcile group cannot be validated since there is no lines." /*)*/;
|
||||||
|
String RECONCILE_GROUP_NO_TEMP_SEQUENCE = /*$$(*/
|
||||||
|
"There is no configured sequence for temporary reconcile group" /*)*/;
|
||||||
|
String RECONCILE_GROUP_NO_FINAL_SEQUENCE = /*$$(*/
|
||||||
|
"There is no configured sequence for final reconcile group" /*)*/;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subrogation Release
|
||||||
|
*/
|
||||||
|
static final String SUBROGATION_RELEASE_MISSING_SEQUENCE = /*$$(*/
|
||||||
|
"Missing subrogation release sequence for company %s" /*)*/;
|
||||||
|
|
||||||
|
/** MoveLine */
|
||||||
|
static final String NO_MOVE_LINE_SELECTED = /*$$(*/ "No Lines selected" /*)*/;
|
||||||
|
|
||||||
|
/** User */
|
||||||
|
static final String USER_PFP_VALIDATOR_COMPANY_SET_NOT_EQUAL = /*$$(*/
|
||||||
|
"%s has not exaclty the same internal companies as %s." /*)*/;
|
||||||
|
|
||||||
|
static final String USER_PFP_VALIDATOR_UPDATED = /*$$(*/
|
||||||
|
"Pfp validator changed successfully" /*)*/;
|
||||||
|
static final String USER_PFP_VALIDATOR_NO_RELATED_ACCOUNTING_SITUATION = /*$$(*/
|
||||||
|
"No Accounting Situation related to %s." /*)*/;
|
||||||
|
|
||||||
|
/* Check refunds */
|
||||||
|
String INVOICE_NOT_IMPUTED_CLIENT_REFUNDS = /*$$(*/
|
||||||
|
"Note: there are existing not imputed client refunds."; /*)*/
|
||||||
|
String INVOICE_NOT_IMPUTED_SUPPLIER_REFUNDS = /*$$(*/
|
||||||
|
"Note: there are existing not imputed supplier refunds."; /*)*/
|
||||||
|
|
||||||
|
public static final String FIXED_ASSET_DISPOSAL_DATE_ERROR_1 = /*$$(*/
|
||||||
|
"Disposal date must be after the date of the last depreciation." /*)*/;
|
||||||
|
public static final String FIXED_ASSET_DISPOSAL_DATE_ERROR_2 = /*$$(*/
|
||||||
|
"Disposal date shouldn't be after the next planned depreciation date. Please realize all depreciations that happened before the disposal." /*)*/;
|
||||||
|
|
||||||
|
/* MOVE REVERSE*/
|
||||||
|
static final String REVERSE_DATE_SELECT_UNKNOW_TYPE = /*$$(*/
|
||||||
|
"There is no reverse date select value of value %d" /*)*/;
|
||||||
|
|
||||||
|
/*Check not lettered advance move lines*/
|
||||||
|
public static final String INVOICE_NOT_LETTERED_SUPPLIER_ADVANCE_MOVE_LINES = /*$$(*/
|
||||||
|
"There is at least one advance payment or payment that can be imputed to this invoice." /*)*/;
|
||||||
|
|
||||||
|
static final String CLOSE_NO_REPORTED_BALANCE_DATE = /*$$(*/
|
||||||
|
"Please set a reported balance date on fiscal year" /*)*/;
|
||||||
|
|
||||||
|
|
||||||
|
String CASH_INVENTORY_MISSING_SEQUENCE = /*$$(*/
|
||||||
|
"There is no configured sequence for cash inventory" /*)*/;
|
||||||
|
}
|
||||||
@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.module;
|
||||||
|
|
||||||
|
import com.axelor.app.AxelorModule;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountAccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountingBatchAccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountingBatchRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountingReportManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountingReportRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AnalyticMoveLineMngtRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AnalyticMoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.DepositSlipAccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.DepositSlipRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.FixedAssetManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.FixedAssetRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceBatchAccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceBatchRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoicePaymentManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoicePaymentRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.JournalManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.JournalRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PartnerAccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentVoucherManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentVoucherRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileGroupAccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileGroupRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.SubrogationReleaseManagementRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.SubrogationReleaseRepository;
|
||||||
|
import com.axelor.apps.account.service.AccountManagementAccountService;
|
||||||
|
import com.axelor.apps.account.service.AccountManagementServiceAccountImpl;
|
||||||
|
import com.axelor.apps.account.service.AccountingCloseAnnualService;
|
||||||
|
import com.axelor.apps.account.service.AccountingCloseAnnualServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.AccountingReportService;
|
||||||
|
import com.axelor.apps.account.service.AccountingReportServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.AccountingSituationService;
|
||||||
|
import com.axelor.apps.account.service.AccountingSituationServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.AddressServiceAccountImpl;
|
||||||
|
import com.axelor.apps.account.service.AnalyticMoveLineService;
|
||||||
|
import com.axelor.apps.account.service.AnalyticMoveLineServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.BankDetailsServiceAccountImpl;
|
||||||
|
import com.axelor.apps.account.service.DepositSlipService;
|
||||||
|
import com.axelor.apps.account.service.DepositSlipServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.FiscalPositionAccountService;
|
||||||
|
import com.axelor.apps.account.service.FiscalPositionAccountServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.FixedAssetLineService;
|
||||||
|
import com.axelor.apps.account.service.FixedAssetLineServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.FixedAssetService;
|
||||||
|
import com.axelor.apps.account.service.FixedAssetServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.MoveLineExportService;
|
||||||
|
import com.axelor.apps.account.service.MoveLineExportServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.NotificationService;
|
||||||
|
import com.axelor.apps.account.service.NotificationServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.PaymentScheduleLineService;
|
||||||
|
import com.axelor.apps.account.service.PaymentScheduleLineServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.PaymentScheduleService;
|
||||||
|
import com.axelor.apps.account.service.PaymentScheduleServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.PeriodServiceAccount;
|
||||||
|
import com.axelor.apps.account.service.PeriodServiceAccountImpl;
|
||||||
|
import com.axelor.apps.account.service.ReconcileGroupSequenceService;
|
||||||
|
import com.axelor.apps.account.service.ReconcileGroupSequenceServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.ReconcileGroupService;
|
||||||
|
import com.axelor.apps.account.service.ReconcileGroupServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.ReconcileService;
|
||||||
|
import com.axelor.apps.account.service.ReconcileServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.SubrogationReleaseService;
|
||||||
|
import com.axelor.apps.account.service.SubrogationReleaseServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.TaxPaymentMoveLineService;
|
||||||
|
import com.axelor.apps.account.service.TaxPaymentMoveLineServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.TemplateMessageAccountService;
|
||||||
|
import com.axelor.apps.account.service.TemplateMessageAccountServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountService;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.extract.ExtractContextMoveService;
|
||||||
|
import com.axelor.apps.account.service.extract.ExtractContextMoveServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.invoice.InvoiceLineService;
|
||||||
|
import com.axelor.apps.account.service.invoice.InvoiceLineServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.invoice.InvoiceService;
|
||||||
|
import com.axelor.apps.account.service.invoice.InvoiceServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.invoice.print.InvoicePrintService;
|
||||||
|
import com.axelor.apps.account.service.invoice.print.InvoicePrintServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.invoice.workflow.cancel.WorkflowCancelService;
|
||||||
|
import com.axelor.apps.account.service.invoice.workflow.cancel.WorkflowCancelServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.invoice.workflow.validate.WorkflowValidationService;
|
||||||
|
import com.axelor.apps.account.service.invoice.workflow.validate.WorkflowValidationServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.invoice.workflow.ventilate.WorkflowVentilationService;
|
||||||
|
import com.axelor.apps.account.service.invoice.workflow.ventilate.WorkflowVentilationServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentModeService;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentModeServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentService;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentCancelService;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentCancelServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentCreateService;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentCreateServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentToolService;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentToolServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentValidateService;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentValidateServiceImpl;
|
||||||
|
import com.axelor.apps.account.service.umr.UmrNumberService;
|
||||||
|
import com.axelor.apps.account.service.umr.UmrNumberServiceImpl;
|
||||||
|
import com.axelor.apps.base.db.repo.PartnerAddressRepository;
|
||||||
|
import com.axelor.apps.base.db.repo.PartnerBaseRepository;
|
||||||
|
import com.axelor.apps.base.service.BankDetailsServiceImpl;
|
||||||
|
import com.axelor.apps.base.service.PeriodServiceImpl;
|
||||||
|
import com.axelor.apps.base.service.tax.AccountManagementServiceImpl;
|
||||||
|
import com.axelor.apps.base.service.tax.FiscalPositionServiceImpl;
|
||||||
|
import com.axelor.apps.message.service.TemplateMessageService;
|
||||||
|
import com.axelor.apps.message.service.TemplateMessageServiceImpl;
|
||||||
|
|
||||||
|
public class AccountModule extends AxelorModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(AddressServiceAccountImpl.class);
|
||||||
|
|
||||||
|
bind(AccountManagementServiceImpl.class).to(AccountManagementServiceAccountImpl.class);
|
||||||
|
|
||||||
|
bind(AccountManagementAccountService.class).to(AccountManagementServiceAccountImpl.class);
|
||||||
|
|
||||||
|
bind(FiscalPositionServiceImpl.class).to(FiscalPositionAccountServiceImpl.class);
|
||||||
|
|
||||||
|
bind(FiscalPositionAccountService.class).to(FiscalPositionAccountServiceImpl.class);
|
||||||
|
|
||||||
|
bind(TemplateMessageService.class).to(TemplateMessageServiceImpl.class);
|
||||||
|
|
||||||
|
bind(InvoiceRepository.class).to(InvoiceManagementRepository.class);
|
||||||
|
|
||||||
|
bind(MoveRepository.class).to(MoveManagementRepository.class);
|
||||||
|
|
||||||
|
bind(MoveLineRepository.class).to(MoveLineManagementRepository.class);
|
||||||
|
|
||||||
|
bind(AccountingReportRepository.class).to(AccountingReportManagementRepository.class);
|
||||||
|
|
||||||
|
bind(AccountingReportService.class).to(AccountingReportServiceImpl.class);
|
||||||
|
|
||||||
|
bind(JournalRepository.class).to(JournalManagementRepository.class);
|
||||||
|
|
||||||
|
bind(PaymentVoucherRepository.class).to(PaymentVoucherManagementRepository.class);
|
||||||
|
|
||||||
|
bind(InvoiceService.class).to(InvoiceServiceImpl.class);
|
||||||
|
|
||||||
|
bind(InvoicePrintService.class).to(InvoicePrintServiceImpl.class);
|
||||||
|
|
||||||
|
bind(PartnerBaseRepository.class).to(PartnerAccountRepository.class);
|
||||||
|
|
||||||
|
bind(AnalyticMoveLineService.class).to(AnalyticMoveLineServiceImpl.class);
|
||||||
|
|
||||||
|
bind(InvoicePaymentRepository.class).to(InvoicePaymentManagementRepository.class);
|
||||||
|
|
||||||
|
bind(InvoicePaymentValidateService.class).to(InvoicePaymentValidateServiceImpl.class);
|
||||||
|
|
||||||
|
bind(InvoicePaymentCreateService.class).to(InvoicePaymentCreateServiceImpl.class);
|
||||||
|
|
||||||
|
bind(InvoicePaymentCancelService.class).to(InvoicePaymentCancelServiceImpl.class);
|
||||||
|
|
||||||
|
bind(InvoicePaymentToolService.class).to(InvoicePaymentToolServiceImpl.class);
|
||||||
|
|
||||||
|
bind(AnalyticMoveLineRepository.class).to(AnalyticMoveLineMngtRepository.class);
|
||||||
|
|
||||||
|
bind(ReconcileService.class).to(ReconcileServiceImpl.class);
|
||||||
|
|
||||||
|
bind(ReconcileRepository.class).to(ReconcileManagementRepository.class);
|
||||||
|
|
||||||
|
bind(AppAccountService.class).to(AppAccountServiceImpl.class);
|
||||||
|
|
||||||
|
bind(AccountingSituationService.class).to(AccountingSituationServiceImpl.class);
|
||||||
|
|
||||||
|
bind(PaymentModeService.class).to(PaymentModeServiceImpl.class);
|
||||||
|
|
||||||
|
bind(BankDetailsServiceImpl.class).to(BankDetailsServiceAccountImpl.class);
|
||||||
|
|
||||||
|
bind(MoveLineExportService.class).to(MoveLineExportServiceImpl.class);
|
||||||
|
|
||||||
|
bind(AccountingBatchRepository.class).to(AccountingBatchAccountRepository.class);
|
||||||
|
|
||||||
|
bind(InvoiceBatchRepository.class).to(InvoiceBatchAccountRepository.class);
|
||||||
|
|
||||||
|
bind(AccountRepository.class).to(AccountAccountRepository.class);
|
||||||
|
|
||||||
|
bind(WorkflowVentilationService.class).to(WorkflowVentilationServiceImpl.class);
|
||||||
|
|
||||||
|
bind(WorkflowCancelService.class).to(WorkflowCancelServiceImpl.class);
|
||||||
|
|
||||||
|
bind(WorkflowValidationService.class).to(WorkflowValidationServiceImpl.class);
|
||||||
|
|
||||||
|
bind(SubrogationReleaseService.class).to(SubrogationReleaseServiceImpl.class);
|
||||||
|
|
||||||
|
bind(NotificationService.class).to(NotificationServiceImpl.class);
|
||||||
|
|
||||||
|
bind(PaymentScheduleService.class).to(PaymentScheduleServiceImpl.class);
|
||||||
|
|
||||||
|
bind(PaymentScheduleLineService.class).to(PaymentScheduleLineServiceImpl.class);
|
||||||
|
|
||||||
|
bind(DepositSlipRepository.class).to(DepositSlipAccountRepository.class);
|
||||||
|
|
||||||
|
bind(DepositSlipService.class).to(DepositSlipServiceImpl.class);
|
||||||
|
|
||||||
|
bind(InvoiceLineService.class).to(InvoiceLineServiceImpl.class);
|
||||||
|
|
||||||
|
bind(TemplateMessageAccountService.class).to(TemplateMessageAccountServiceImpl.class);
|
||||||
|
|
||||||
|
PartnerAddressRepository.modelPartnerFieldMap.put(Invoice.class.getName(), "partner");
|
||||||
|
|
||||||
|
bind(UmrNumberService.class).to(UmrNumberServiceImpl.class);
|
||||||
|
|
||||||
|
bind(ReconcileGroupSequenceService.class).to(ReconcileGroupSequenceServiceImpl.class);
|
||||||
|
|
||||||
|
bind(ReconcileGroupRepository.class).to(ReconcileGroupAccountRepository.class);
|
||||||
|
|
||||||
|
bind(ReconcileGroupService.class).to(ReconcileGroupServiceImpl.class);
|
||||||
|
|
||||||
|
bind(SubrogationReleaseRepository.class).to(SubrogationReleaseManagementRepository.class);
|
||||||
|
|
||||||
|
bind(PeriodServiceImpl.class).to(PeriodServiceAccountImpl.class);
|
||||||
|
|
||||||
|
bind(FixedAssetRepository.class).to(FixedAssetManagementRepository.class);
|
||||||
|
|
||||||
|
bind(FixedAssetService.class).to(FixedAssetServiceImpl.class);
|
||||||
|
|
||||||
|
bind(FixedAssetLineService.class).to(FixedAssetLineServiceImpl.class);
|
||||||
|
|
||||||
|
bind(ExtractContextMoveService.class).to(ExtractContextMoveServiceImpl.class);
|
||||||
|
|
||||||
|
bind(AccountingCloseAnnualService.class).to(AccountingCloseAnnualServiceImpl.class);
|
||||||
|
|
||||||
|
bind(PeriodServiceAccount.class).to(PeriodServiceAccountImpl.class);
|
||||||
|
|
||||||
|
bind(MoveService.class).to(MoveServiceImpl.class);
|
||||||
|
|
||||||
|
bind(TaxPaymentMoveLineService.class).to(TaxPaymentMoveLineServiceImpl.class);
|
||||||
|
|
||||||
|
bind(PaymentService.class).to(PaymentServiceImpl.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.report;
|
||||||
|
|
||||||
|
public interface IReport {
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_TYPE = "AccountingReportType%s.rptdesign";
|
||||||
|
public static final String PAYMENT_VOUCHER = "PaymentVoucher.rptdesign";
|
||||||
|
public static final String IRRECOVERABLE = "Irrecoverable.rptdesign";
|
||||||
|
public static final String INVOICE = "Invoice.rptdesign";
|
||||||
|
public static final String SALE_INVOICES_DETAILS = "SaleInvoicesDetails.rptdesign";
|
||||||
|
public static final String PURCHASE_INVOICES_DETAILS = "PurchaseInvoicesDetails.rptdesign";
|
||||||
|
public static final String ACCOUNT_MOVE = "AccountMove.rptdesign";
|
||||||
|
public static final String SUBROGATION_RELEASE = "SubrogationRelease.rptdesign";
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP = "ChequeDepositSlip.rptdesign";
|
||||||
|
public static final String CASH_DEPOSIT_SLIP = "CashDepositSlip.rptdesign";
|
||||||
|
public static final String CASH_INVENTORY = "CashInventory%s.rptdesign";
|
||||||
|
}
|
||||||
@ -0,0 +1,510 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.report;
|
||||||
|
|
||||||
|
public interface ITranslation {
|
||||||
|
|
||||||
|
public static final String INVOICE_ADVANCE_PAYMENTS = /*$$(*/ "Invoice.advancePayments"; /*)*/
|
||||||
|
public static final String INVOICE_DATE = /*$$(*/ "Invoice.date"; /*)*/
|
||||||
|
public static final String INVOICE_PAYMENT_TERMS = /*$$(*/ "Invoice.paymentTerms"; /*)*/
|
||||||
|
public static final String INVOICE_DUE_DATE = /*$$(*/ "Invoice.dueDate"; /*)*/
|
||||||
|
public static final String INVOICE_DOCUMENT_REF = /*$$(*/ "Invoice.documentRef"; /*)*/
|
||||||
|
public static final String INVOICE_SUPPLIER = /*$$(*/ "Invoice.supplier"; /*)*/
|
||||||
|
public static final String INVOICE_DESCRIPTION = /*$$(*/ "Invoice.description"; /*)*/
|
||||||
|
public static final String INVOICE_TAX = /*$$(*/ "Invoice.tax"; /*)*/
|
||||||
|
public static final String INVOICE_QTY_UNIT = /*$$(*/ "Invoice.qtyUnit"; /*)*/
|
||||||
|
public static final String INVOICE_UNIT_PRICE = /*$$(*/ "Invoice.unitPrice"; /*)*/
|
||||||
|
public static final String INVOICE_PRICE_EXCL_TAX = /*$$(*/ "Invoice.priceExclTax"; /*)*/
|
||||||
|
public static final String INVOICE_PRICE_INCL_TAX = /*$$(*/ "Invoice.priceInclTax"; /*)*/
|
||||||
|
public static final String INVOICE_BASE = /*$$(*/ "Invoice.base"; /*)*/
|
||||||
|
public static final String INVOICE_TAX_AMOUNT = /*$$(*/ "Invoice.taxAmount"; /*)*/
|
||||||
|
public static final String INVOICE_TOTAL_EXCL_TAX = /*$$(*/ "Invoice.totalExclTax"; /*)*/
|
||||||
|
public static final String INVOICE_TOTAL_EXCL_TAX_WITHOUT_DISCOUNT = /*$$(*/
|
||||||
|
"Invoice.totalExclTaxWithoutDiscount"; /*)*/
|
||||||
|
public static final String INVOICE_TOTAL_TAX = /*$$(*/ "Invoice.totalTax"; /*)*/
|
||||||
|
public static final String INVOICE_TOTAL_INCL_TAX = /*$$(*/ "Invoice.totalInclTax"; /*)*/
|
||||||
|
public static final String INVOICE_TOTAL_DISCOUNT = /*$$(*/ "Invoice.totalDiscount"; /*)*/
|
||||||
|
public static final String INVOICE_AFTER_DISCOUNT = /*$$(*/ "Invoice.afterDiscount"; /*)*/
|
||||||
|
public static final String INVOICE_NOTE = /*$$(*/ "Invoice.note"; /*)*/
|
||||||
|
public static final String INVOICE_CHEQUE = /*$$(*/ "Invoice.cheque"; /*)*/
|
||||||
|
public static final String INVOICE_BANK_DETAILS = /*$$(*/ "Invoice.bankDetails"; /*)*/
|
||||||
|
public static final String INVOICE_BANKING_INFO = /*$$(*/ "Invoice.bankingInfo"; /*)*/
|
||||||
|
public static final String INVOICE_CLIENT_REF = /*$$(*/ "Invoice.clientRef"; /*)*/
|
||||||
|
public static final String INVOICE_SUPPLY_REF = /*$$(*/ "Invoice.supplyRef"; /*)*/
|
||||||
|
public static final String INVOICE_PURCHASE_INVOICE_NO = /*$$(*/
|
||||||
|
"Invoice.purchaseInvoiceNo"; /*)*/
|
||||||
|
public static final String INVOICE_PURCHASE_INVOICE_ADV_PAYMENT_NO = /*$$(*/
|
||||||
|
"Invoice.purchaseInvoiceAdvPaymentNo"; /*)*/
|
||||||
|
public static final String INVOICE_PURCHASE_INVOICE_BALANCE_NO = /*$$(*/
|
||||||
|
"Invoice.purchaseInvoiceBalanceNo"; /*)*/
|
||||||
|
public static final String INVOICE_PURCHASE_REFUND_NO = /*$$(*/ "Invoice.purchaseRefundNo"; /*)*/
|
||||||
|
public static final String INVOICE_INVOICE_NO = /*$$(*/ "Invoice.invoiceNo"; /*)*/
|
||||||
|
public static final String INVOICE_INVOICE_ADV_PAYMENT_NO = /*$$(*/
|
||||||
|
"Invoice.invoiceAdvPaymentNo"; /*)*/
|
||||||
|
public static final String INVOICE_INVOICE_BALANCE_NO = /*$$(*/ "Invoice.invoiceBalanceNo"; /*)*/
|
||||||
|
public static final String INVOICE_DRAFT_INVOICE_NO = /*$$(*/ "Invoice.draftInvoiceNo"; /*)*/
|
||||||
|
public static final String INVOICE_REFUND_NO = /*$$(*/ "Invoice.refundNo"; /*)*/
|
||||||
|
public static final String INVOICE_DISCOUNT_AMOUNT = /*$$(*/ "Invoice.discountAmount"; /*)*/
|
||||||
|
public static final String INVOICE_ADVANCE_PAYMENT = /*$$(*/ "Invoice.advancePayment"; /*)*/
|
||||||
|
public static final String INVOICE_OF = /*$$(*/ "Invoice.of"; /*)*/
|
||||||
|
public static final String INVOICE_IMPUTED_ON = /*$$(*/ "Invoice.imputedOn"; /*)*/
|
||||||
|
public static final String INVOICE_TOTAL_TO_PAY = /*$$(*/ "Invoice.totalToPay"; /*)*/
|
||||||
|
public static final String INVOICE_CANCEL_INVOICE_NO = /*$$(*/ "Invoice.cancelInvoiceNo"; /*)*/
|
||||||
|
|
||||||
|
public static final String INVOICE_TIMESHEET_TITLE = /*$$(*/ "Invoice.timesheetTitle"; /*)*/
|
||||||
|
public static final String INVOICE_EXPENSE_TITLE = /*$$(*/ "Invoice.expenseTitle"; /*)*/
|
||||||
|
|
||||||
|
public static final String INVOICE_TIMESHEET_USER = /*$$(*/ "Invoice.timesheetUser"; /*)*/
|
||||||
|
public static final String INVOICE_TIMESHEET_ACTIVITY = /*$$(*/ "Invoice.timesheetActivity"; /*)*/
|
||||||
|
public static final String INVOICE_TIMESHEET_DURATION = /*$$(*/ "Invoice.timesheetDuration"; /*)*/
|
||||||
|
|
||||||
|
public static final String INVOICE_EXPENSE_TOTAL_AMOUNT = /*$$(*/
|
||||||
|
"Invoice.expenseTotalAmount"; /*)*/
|
||||||
|
public static final String INVOICE_EXPENSE_TAX_AMOUNT = /*$$(*/ "Invoice.expenseTaxAmount"; /*)*/
|
||||||
|
public static final String INVOICE_EXPENSE_PRODUCT = /*$$(*/ "Invoice.expenseProduct"; /*)*/
|
||||||
|
|
||||||
|
public static final String INVOICE_PRODUCT_CODE = /*$$(*/ "Invoice.productCode"; /*)*/
|
||||||
|
public static final String INVOICE_TERMS_AND_CONDITIONS = /*$$(*/
|
||||||
|
"Invoice.termsAndConditions"; /*)*/
|
||||||
|
|
||||||
|
public static final String INVOICE_SUBSCRIPTION_PERIOD = /*$$(*/
|
||||||
|
"Invoice.subscriptionPeriod"; /*)*/
|
||||||
|
public static final String INVOICE_CUSTOMER_PARTNER_SEQ = /*$$(*/
|
||||||
|
"Invoice.customerPartnerSeq"; /*)*/
|
||||||
|
public static final String INVOICE_SUPPLIER_PARTNER_SEQ = /*$$(*/
|
||||||
|
"Invoice.supplierPartnerSeq"; /*)*/
|
||||||
|
public static final String INVOICE_CUSTOMER_TAX_NUMBER = /*$$(*/
|
||||||
|
"Invoice.customerTaxNumber"; /*)*/
|
||||||
|
public static final String INVOICE_AMOUNT_REMAINING = /*$$(*/ "Invoice.amountRemaining"; /*)*/
|
||||||
|
public static final String INVOICE_PROFORMA_INVOICE = /*$$(*/ "Invoice.proformaInvoice"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_EDITION_DATE = /*$$(*/
|
||||||
|
"AccountingReport.editionDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_RECAP_BY_ACCOUNT = /*$$(*/
|
||||||
|
"AccountingReport.recapByAccount"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_TOTAL_DEBIT_ACCOUNT = /*$$(*/
|
||||||
|
"AccountingReport.totalDebitAccount"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_TOTAL_CREDIT_ACCOUNT = /*$$(*/
|
||||||
|
"AccountingReport.totalCreditAccount"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_CONTROL = /*$$(*/ "AccountingReport.control"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_1_TITLE = /*$$(*/
|
||||||
|
"AccountingReportType1.title"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_JOURNAL = /*$$(*/
|
||||||
|
"AccountingReportType1.journal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_COMPANY = /*$$(*/
|
||||||
|
"AccountingReportType1.company"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_END_DATE = /*$$(*/
|
||||||
|
"AccountingReportType1.endDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_FROM = /*$$(*/ "AccountingReportType1.from"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_TO = /*$$(*/ "AccountingReportType1.to"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_PERIOD = /*$$(*/
|
||||||
|
"AccountingReportType1.period"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_PAYMENT_MODE = /*$$(*/
|
||||||
|
"AccountingReportType1.paymentMode"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_DATE = /*$$(*/ "AccountingReportType1.date"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_1_CODE = /*$$(*/ "AccountingReportType1.code"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_1_NAME = /*$$(*/ "AccountingReportType1.name"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_1_DESCRIPTION = /*$$(*/
|
||||||
|
"AccountingReportType1.description"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_PARTNER = /*$$(*/
|
||||||
|
"AccountingReportType1.partner"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_BALANCE = /*$$(*/
|
||||||
|
"AccountingReportType1.balance"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_DEBIT = /*$$(*/
|
||||||
|
"AccountingReportType1.debit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_CREDIT = /*$$(*/
|
||||||
|
"AccountingReportType1.credit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_1_TOTAL = /*$$(*/
|
||||||
|
"AccountingReportType1.total"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_7_TITLE = /*$$(*/
|
||||||
|
"AccountingReportType7.title"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_DUE_DATE = /*$$(*/
|
||||||
|
"AccountingReportType7.dueDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_RECONCILE_GROUP = /*$$(*/
|
||||||
|
"AccountingReportType7.reconcileGroup"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_JOURNAL_DATE = /*$$(*/
|
||||||
|
"AccountingReportType7.journalCode"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_JOURNAL = /*$$(*/
|
||||||
|
"AccountingReportType1.journal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_COMPANY = /*$$(*/
|
||||||
|
"AccountingReportType1.company"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_END_DATE = /*$$(*/
|
||||||
|
"AccountingReportType1.endDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_FROM = /*$$(*/ "AccountingReportType1.from"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_TO = /*$$(*/ "AccountingReportType1.to"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_PERIOD = /*$$(*/
|
||||||
|
"AccountingReportType1.period"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_PAYMENT_MODE = /*$$(*/
|
||||||
|
"AccountingReportType1.paymentMode"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_DATE = /*$$(*/ "AccountingReportType1.date"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_DESCRIPTION = /*$$(*/
|
||||||
|
"AccountingReportType1.description"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_PARTNER = /*$$(*/
|
||||||
|
"AccountingReportType1.partner"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_BALANCE = /*$$(*/
|
||||||
|
"AccountingReportType1.balance"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_DEBIT = /*$$(*/
|
||||||
|
"AccountingReportType1.debit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_CREDIT = /*$$(*/
|
||||||
|
"AccountingReportType1.credit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_7_TOTAL = /*$$(*/
|
||||||
|
"AccountingReportType1.total"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_2_TITLE = /*$$(*/
|
||||||
|
"AccountingReportType2.title"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_JOURNAL = /*$$(*/
|
||||||
|
"AccountingReportType2.journal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_COMPANY = /*$$(*/
|
||||||
|
"AccountingReportType2.company"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_END_DATE = /*$$(*/
|
||||||
|
"AccountingReportType2.endDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_FROM = /*$$(*/ "AccountingReportType2.from"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_TO = /*$$(*/ "AccountingReportType2.to"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_PERIOD = /*$$(*/
|
||||||
|
"AccountingReportType2.period"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_PAYMENT_MODE = /*$$(*/
|
||||||
|
"AccountingReportType2.paymentMode"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_ACCOUNT = /*$$(*/
|
||||||
|
"AccountingReportType2.account"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_ACCOUNT_LABEL = /*$$(*/
|
||||||
|
"AccountingReportType2.accountLabel"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_TOTAL_DEBIT = /*$$(*/
|
||||||
|
"AccountingReportType2.totalDebit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_TOTAL_CREDIT = /*$$(*/
|
||||||
|
"AccountingReportType2.totalCredit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_BALANCE = /*$$(*/
|
||||||
|
"AccountingReportType2.balance"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_DEBIT = /*$$(*/
|
||||||
|
"AccountingReportType2.debit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_CREDIT = /*$$(*/
|
||||||
|
"AccountingReportType2.credit"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2_GENERAL_BALANCE = /*$$(*/
|
||||||
|
"AccountingReportType2.generalBalance"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_6_TITLE = /*$$(*/
|
||||||
|
"AccountingReportType6.title"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_15_TITLE = /*$$(*/
|
||||||
|
"AccountingReportType15.title"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_COMPANY = /*$$(*/
|
||||||
|
"AccountingReportType15.company"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_FROM = /*$$(*/
|
||||||
|
"AccountingReportType15.from"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_TO = /*$$(*/ "AccountingReportType15.to"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_YEAR = /*$$(*/
|
||||||
|
"AccountingReportType15.year"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_VAT_TOTAL = /*$$(*/
|
||||||
|
"AccountingReportType15.vatTotal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_PRINT_DATE = /*$$(*/
|
||||||
|
"AccountingReportType15.printDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_CURRENCY = /*$$(*/
|
||||||
|
"AccountingReportType15.currency"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_TAX_CODE = /*$$(*/
|
||||||
|
"AccountingReportType15.taxCode"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_NAME = /*$$(*/
|
||||||
|
"AccountingReportType15.name"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_MOVE_LINE = /*$$(*/
|
||||||
|
"AccountingReportType15.moveLine"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_DATE = /*$$(*/
|
||||||
|
"AccountingReportType15.date"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_MOVE_LINE_ACCOUNT = /*$$(*/
|
||||||
|
"AccountingReportType15.moveLineAccount"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_ACCOUNT_NAME = /*$$(*/
|
||||||
|
"AccountingReportType15.accountName"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_BASE = /*$$(*/
|
||||||
|
"AccountingReportType15.base"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_VAT_CASH_ACCOUNTING_SCHEME = /*$$(*/
|
||||||
|
"AccountingReportType15.vatCashAccountingScheme"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_PAYABLE_VAT = /*$$(*/
|
||||||
|
"AccountingReportType15.payableVAT"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_DEDUCTIBLE_VAT = /*$$(*/
|
||||||
|
"AccountingReportType15.deductibleVAT"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_REPORT_DATE_EDITION = /*$$(*/
|
||||||
|
"AccountingReportType15.reportDateEdition"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_TOTAL = /*$$(*/
|
||||||
|
"AccountingReportType15.total"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_BLANCE = /*$$(*/
|
||||||
|
"AccountingReportType15.balance"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_AMOUNT = /*$$(*/
|
||||||
|
"AccountingReportType15.amount"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_15_TAX_RATE = /*$$(*/
|
||||||
|
"AccountingReportType15.taxRate"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_11_JOURNAL = /*$$(*/
|
||||||
|
"AccountingReportType11.daySubTotal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_TITLE = /*$$(*/
|
||||||
|
"AccountingReportType2000.title"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ANALYTIC_JOURNAL = /*$$(*/
|
||||||
|
"AccountingReportType2000.analyticJournal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_COMPANY = /*$$(*/
|
||||||
|
"AccountingReportType2000.company"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_END_DATE = /*$$(*/
|
||||||
|
"AccountingReportType2000.endDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_FROM = /*$$(*/
|
||||||
|
"AccountingReportType2000.from"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_TO = /*$$(*/
|
||||||
|
"AccountingReportType2000.to"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ANALYTIC_AXIS = /*$$(*/
|
||||||
|
"AccountingReportType2000.analyticAxis"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ANALYTIC_AXIS_CODE = /*$$(*/
|
||||||
|
"AccountingReportType2000.analyticAxisCode"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ANALYTIC_AXIS_NAME = /*$$(*/
|
||||||
|
"AccountingReportType2000.analyticAxisName"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ANALYTIC_ACCOUNT = /*$$(*/
|
||||||
|
"AccountingReportType2000.analyticAccount"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ANALYTIC_ACCOUNT_CODE = /*$$(*/
|
||||||
|
"AccountingReportType2000.analyticAccountCode"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ANALYTIC_ACCOUNT_NAME = /*$$(*/
|
||||||
|
"AccountingReportType2000.analyticAccountName"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_ACCOUNT_TYPE = /*$$(*/
|
||||||
|
"AccountingReportType2000.accountType"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_AMOUNT = /*$$(*/
|
||||||
|
"AccountingReportType2000.amount"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_PERCENTAGE = /*$$(*/
|
||||||
|
"AccountingReportType2000.percentage"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_TOTAL_PER_ANALYTIC_JOURNAL = /*$$(*/
|
||||||
|
"AccountingReportType2000.totalPerAnalyticJournal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_TOTAL_PER_ANALYTIC_AXIS = /*$$(*/
|
||||||
|
"AccountingReportType2000.totalPerAnalyticAxis"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_2000_TOTAL_PER_ANALYTIC_ACCOUNT = /*$$(*/
|
||||||
|
"AccountingReportType2000.totalPerAnalyticAccount"; /*)*/
|
||||||
|
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_TITLE = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.title"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_COMPANY = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.company"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_PUBLICATION_DATE = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.publicationDate"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_PRODUCT_CATEGORIES = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.productCategories"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_INVOICED = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.invoiced"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_ORDERED = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.ordered"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_SUBTOTAL = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.subtotal"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_SUM_BY_PARTNER = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.sumByPartner"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_SUM_BY_PRODUCT = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.sumByProduct"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_TOTAL_ORDER = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.totalOrder"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_TOTAL_INVOICE = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.totalInvoice"; /*)*/
|
||||||
|
public static final String SALE_INVOICE_DETAILS_REPORT_TOTAL_TURNOVER = /*$$(*/
|
||||||
|
"SaleInvoicesDetails.totalTurnover"; /*)*/
|
||||||
|
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_TITLE = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.title"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_COMPANY = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.company"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_PUBLICATION_DATE = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.publicationDate"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_ETAILS_REPORT_PRODUCT_CATEGORIES = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.productCategories"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_INVOICED = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.invoiced"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_ORDERED = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.ordered"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_SUBTOTAL = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.subtotal"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_SUM_BY_PARTNER = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.sumByPartner"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_SUM_BY_PRODUCT = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.sumByProduct"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_TOTAL_ORDER = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.totalOrder"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_TOTAL_INVOICE = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.totalInvoice"; /*)*/
|
||||||
|
public static final String PURCHASE_INVOICE_DETAILS_REPORT_TOTAL_TURNOVER = /*$$(*/
|
||||||
|
"PurchaseInvoicesDetails.totalTurnover"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNT_MOVE_TITLE = /*$$(*/ "move.title"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_REFERENCE = /*$$(*/ "move.reference"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_JOURNAL = /*$$(*/ "move.journal"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_PARTNER = /*$$(*/ "move.partner"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_TECHNICAL_ORIGIN = /*$$(*/ "move.technical.origin"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_PERIOD = /*$$(*/ "move.period"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_CURRENCY = /*$$(*/ "move.currency"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_COMPANY = /*$$(*/ "move.company"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_DATE = /*$$(*/ "moveLine.date"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_PARTNER = /*$$(*/ "moveLine.partner"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_ACCOUNT = /*$$(*/ "moveLine.account"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_DEBIT = /*$$(*/ "moveLine.debit"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_CREDIT = /*$$(*/ "moveLine.credit"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_CURRENCY_AMOUNT = /*$$(*/
|
||||||
|
"moveLine.currency.amount"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_TAX_RATE = /*$$(*/ "moveLine.tax.rate"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_RECONCILE_LIST = /*$$(*/
|
||||||
|
"moveLine.reconcile.list"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_DESC = /*$$(*/ "moveLine.description"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_ORIGIN = /*$$(*/ "moveLine.origin"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_RECONCILE_GROUP = /*$$(*/
|
||||||
|
"moveLine.reconcileGroup"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_TOTAL_LINES = /*$$(*/ "moveLine.totalLines"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_TOTAL_DEBIT = /*$$(*/ "moveLine.totalDebit"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_TOTAL_CREDIT = /*$$(*/ "moveLine.totalCredit"; /*)*/
|
||||||
|
public static final String ACCOUNT_MOVE_LINE_DIFFERENCE = /*$$(*/ "moveLine.difference"; /*)*/
|
||||||
|
|
||||||
|
public static final String SUBROGATION_RELEASE_TITLE = /*$$(*/ "SubrogationRelease.title"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_SELLER_CODE = /*$$(*/
|
||||||
|
"SubrogationRelease.sellerCode"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_FACTOR = /*$$(*/ "SubrogationRelease.factor"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_PARTNER_SEQ = /*$$(*/
|
||||||
|
"SubrogationRelease.partnerSeq"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_INVOICE_ID = /*$$(*/
|
||||||
|
"SubrogationRelease.invoiceId"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_INVOICE_DATE = /*$$(*/
|
||||||
|
"SubrogationRelease.invoiceDate"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_DUE_DATE = /*$$(*/
|
||||||
|
"SubrogationRelease.dueDate"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_IN_TAX_TOTAL = /*$$(*/
|
||||||
|
"SubrogationRelease.inTaxtTotal"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_CURRENCY_CODE = /*$$(*/
|
||||||
|
"SubrogationRelease.currencyCode"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_INVOICE_TOTAL = /*$$(*/
|
||||||
|
"SubrogationRelease.invoiceTotal"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_CREDIT_TOTAL = /*$$(*/
|
||||||
|
"SubrogationRelease.creditTotal"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_GRAND_TOTAL = /*$$(*/
|
||||||
|
"SubrogationRelease.grandTotal"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_COMPANY_NAME = /*$$(*/
|
||||||
|
"SubrogationRelease.company"; /*)*/
|
||||||
|
public static final String SUBROGATION_RELEASE_SEQUENCE_NUMBER = /*$$(*/
|
||||||
|
"SubrogationRelease.sequenceNumber"; /*)*/
|
||||||
|
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_TITLE = /*$$(*/ "ChequeDepositSlip.title"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_PRINTED_ON = /*$$(*/
|
||||||
|
"ChequeDepositSlip.printedOn"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_NUMBER = /*$$(*/ "ChequeDepositSlip.number"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_DATE = /*$$(*/
|
||||||
|
"ChequeDepositSlip.depositDate"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_CHEQUE_NUMBERS = /*$$(*/
|
||||||
|
"ChequeDepositSlip.chequeNumbers"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_BANK = /*$$(*/ "ChequeDepositSlip.bank"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_ACCOUNT_NUMBER = /*$$(*/
|
||||||
|
"ChequeDepositSlip.accountNumber"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_INDIVIDUAL = /*$$(*/
|
||||||
|
"ChequeDepositSlip.individual"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_ISSUER = /*$$(*/ "ChequeDepositSlip.issuer"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_PAYER = /*$$(*/ "ChequeDepositSlip.payer"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_CHEQUE_NUMBER = /*$$(*/
|
||||||
|
"ChequeDepositSlip.chequeNumber"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_PAYMENT_DATE = /*$$(*/
|
||||||
|
"ChequeDepositSlip.paymentDate"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_CHEQUE_DATE = /*$$(*/
|
||||||
|
"ChequeDepositSlip.chequeDate"; /*)*/
|
||||||
|
public static final String CHEQUE_DEPOSIT_SLIP_AMOUNT = /*$$(*/ "ChequeDepositSlip.amount"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_16_TITLE =
|
||||||
|
/*$$(*/ "AccountingReportType16.title"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_16_COMPANY =
|
||||||
|
/*$$(*/ "AccountingReportType16.company"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_CURRENCY =
|
||||||
|
/*$$(*/ "AccountingReportType16.currency"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_END_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType16.endDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_YEAR =
|
||||||
|
/*$$(*/ "AccountingReportType16.year"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_PERIOD =
|
||||||
|
/*$$(*/ "AccountingReportType16.period"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_FROM_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType16.from"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_TO_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType16.to"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_16_REFERENCE =
|
||||||
|
/*$$(*/ "AccountingReportType16.reference"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_ASSET_NAME =
|
||||||
|
/*$$(*/ "AccountingReportType16.asset_name"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_ACCOUNT_NAME =
|
||||||
|
/*$$(*/ "AccountingReportType16.account_name"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_COMPUTATION_METHOD =
|
||||||
|
/*$$(*/ "AccountingReportType16.computaion_method"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_DURATION =
|
||||||
|
/*$$(*/ "AccountingReportType16.duration"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_ACQISITION_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType16.acquisition_date"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_16_GROSS_VALUE =
|
||||||
|
/*$$(*/ "AccountingReportType16.gross_value"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_ASSET_COMPUTATION_METHOD_LINEAR =
|
||||||
|
/*$$(*/ "linear"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_ASSET_COMPUTATION_METHOD_DIGRESSIVE =
|
||||||
|
/*$$(*/ "degressive"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_17_TITLE =
|
||||||
|
/*$$(*/ "AccountingReportType17.title"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_17_COMPANY =
|
||||||
|
/*$$(*/ "AccountingReportType17.company"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_CURRENCY =
|
||||||
|
/*$$(*/ "AccountingReportType17.currency"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_END_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType17.endDate"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_YEAR =
|
||||||
|
/*$$(*/ "AccountingReportType17.year"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_PERIOD =
|
||||||
|
/*$$(*/ "AccountingReportType17.period"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_FROM_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType17.from"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_TO_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType17.to"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_17_REFERENCE =
|
||||||
|
/*$$(*/ "AccountingReportType17.reference"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_ASSET_NAME =
|
||||||
|
/*$$(*/ "AccountingReportType17.asset_name"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_COMPUTATION_METHOD =
|
||||||
|
/*$$(*/ "AccountingReportType17.computation_method"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_DURATION =
|
||||||
|
/*$$(*/ "AccountingReportType17.duration"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_ACQISITION_DATE =
|
||||||
|
/*$$(*/ "AccountingReportType17.acquisition_date"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_RESIDUAL_VALUE =
|
||||||
|
/*$$(*/ "AccountingReportType17.residual_value"; /*)*/
|
||||||
|
|
||||||
|
public static final String ACCOUNTING_REPORT_17_GROSS_VALUES =
|
||||||
|
/*$$(*/ "AccountingReportType17.gross_values"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_ORIGINAL_VALUE =
|
||||||
|
/*$$(*/ "AccountingReportType17.original_value"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_ACQISITION =
|
||||||
|
/*$$(*/ "AccountingReportType17.acquisition"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_ASSET_DISPOSAL =
|
||||||
|
/*$$(*/ "AccountingReportType17.asset_disposal"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_YEAR_END_VALUE =
|
||||||
|
/*$$(*/ "AccountingReportType17.year_end_value"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_DEPRECIATION =
|
||||||
|
/*$$(*/ "AccountingReportType17.depreciation"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_YEAR_START_VALUE =
|
||||||
|
/*$$(*/ "AccountingReportType17.year_start_value"; /*)*/
|
||||||
|
public static final String ACCOUNTING_REPORT_17_DEPRECIATION_CHARGE =
|
||||||
|
/*$$(*/ "AccountingReportType17.depreciation_charge"; /*)*/
|
||||||
|
|
||||||
|
public static final String INVOICE_PAYMENT_DATE = /*$$(*/ "InvoicePayment.date"; /*)*/
|
||||||
|
public static final String INVOICE_PAYMENT_TYPE = /*$$(*/ "InvoicePayment.type"; /*)*/
|
||||||
|
public static final String INVOICE_PAYMENT_PAYMENT_MODE = /*$$(*/
|
||||||
|
"InvoicePayment.payment_mode"; /*)*/
|
||||||
|
public static final String INVOICE_PAYMENT_AMOUNT = /*$$(*/ "InvoicePayment.amount"; /*)*/
|
||||||
|
}
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountChart;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountChartRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountConfigRepository;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.ImportConfiguration;
|
||||||
|
import com.axelor.apps.base.db.repo.CompanyRepository;
|
||||||
|
import com.axelor.apps.base.service.imports.importer.FactoryImporter;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.service.TraceBackService;
|
||||||
|
import com.axelor.meta.MetaFiles;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
public class AccountChartService {
|
||||||
|
|
||||||
|
@Inject private FactoryImporter factoryImporter;
|
||||||
|
|
||||||
|
@Inject private MetaFiles metaFiles;
|
||||||
|
|
||||||
|
protected AccountConfigRepository accountConfigRepo;
|
||||||
|
protected CompanyRepository companyRepo;
|
||||||
|
protected AccountChartRepository accountChartRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountChartService(
|
||||||
|
AccountConfigRepository accountConfigRepo,
|
||||||
|
CompanyRepository companyRepo,
|
||||||
|
AccountChartRepository accountChartRepository) {
|
||||||
|
|
||||||
|
this.accountConfigRepo = accountConfigRepo;
|
||||||
|
this.companyRepo = companyRepo;
|
||||||
|
this.accountChartRepository = accountChartRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean installAccountChart(AccountChart act, Company company, AccountConfig accountConfig)
|
||||||
|
throws AxelorException {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (act.getMetaFile() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream inputStream = this.getClass().getResourceAsStream("/l10n/chart-config.xml");
|
||||||
|
if (inputStream == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File configFile = createConfigFile(inputStream);
|
||||||
|
|
||||||
|
Map<String, Object> importContext = new HashMap<String, Object>();
|
||||||
|
importContext.put("_companyId", company.getId());
|
||||||
|
|
||||||
|
importAccountChartData(act, configFile, importContext);
|
||||||
|
|
||||||
|
updateChartCompany(act, company, accountConfig);
|
||||||
|
|
||||||
|
FileUtils.forceDelete(configFile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
TraceBackService.trace(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File createConfigFile(InputStream inputStream) throws IOException, FileNotFoundException {
|
||||||
|
|
||||||
|
File configFile = File.createTempFile("input-config", ".xml");
|
||||||
|
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(configFile);
|
||||||
|
int read = 0;
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
while ((read = inputStream.read(bytes)) != -1) {
|
||||||
|
outputStream.write(bytes, 0, read);
|
||||||
|
}
|
||||||
|
outputStream.close();
|
||||||
|
|
||||||
|
return configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateChartCompany(AccountChart act, Company company, AccountConfig accountConfig) {
|
||||||
|
|
||||||
|
accountConfig = accountConfigRepo.find(accountConfig.getId());
|
||||||
|
accountConfig.setHasChartImported(true);
|
||||||
|
accountConfigRepo.save(accountConfig);
|
||||||
|
act = accountChartRepository.find(act.getId());
|
||||||
|
company = companyRepo.find(company.getId());
|
||||||
|
Set<Company> companySet = act.getCompanySet();
|
||||||
|
companySet.add(company);
|
||||||
|
act.setCompanySet(companySet);
|
||||||
|
accountChartRepository.save(act);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void importAccountChartData(
|
||||||
|
AccountChart act, File configFile, Map<String, Object> importContext)
|
||||||
|
throws IOException, AxelorException {
|
||||||
|
|
||||||
|
ImportConfiguration importConfiguration = new ImportConfiguration();
|
||||||
|
importConfiguration.setDataMetaFile(act.getMetaFile());
|
||||||
|
importConfiguration.setBindMetaFile(metaFiles.upload(configFile));
|
||||||
|
|
||||||
|
factoryImporter.createImporter(importConfiguration).run(importContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,319 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountClearance;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.account.db.Tax;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountClearanceRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.move.MoveLineService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.apps.base.service.tax.TaxService;
|
||||||
|
import com.axelor.apps.base.service.user.UserService;
|
||||||
|
import com.axelor.auth.db.User;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AccountClearanceService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected MoveService moveService;
|
||||||
|
protected MoveLineService moveLineService;
|
||||||
|
protected MoveLineRepository moveLineRepo;
|
||||||
|
protected SequenceService sequenceService;
|
||||||
|
protected ReconcileService reconcileService;
|
||||||
|
protected TaxService taxService;
|
||||||
|
protected TaxAccountService taxAccountService;
|
||||||
|
protected AccountClearanceRepository accountClearanceRepo;
|
||||||
|
protected AppBaseService appBaseService;
|
||||||
|
protected User user;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountClearanceService(
|
||||||
|
UserService userService,
|
||||||
|
AppBaseService appBaseService,
|
||||||
|
MoveService moveService,
|
||||||
|
MoveLineService moveLineService,
|
||||||
|
MoveLineRepository moveLineRepo,
|
||||||
|
SequenceService sequenceService,
|
||||||
|
ReconcileService reconcileService,
|
||||||
|
TaxService taxService,
|
||||||
|
TaxAccountService taxAccountService,
|
||||||
|
AccountClearanceRepository accountClearanceRepo) {
|
||||||
|
|
||||||
|
this.appBaseService = appBaseService;
|
||||||
|
this.user = userService.getUser();
|
||||||
|
this.moveService = moveService;
|
||||||
|
this.moveLineService = moveLineService;
|
||||||
|
this.moveLineRepo = moveLineRepo;
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
this.reconcileService = reconcileService;
|
||||||
|
this.taxService = taxService;
|
||||||
|
this.taxAccountService = taxAccountService;
|
||||||
|
this.accountClearanceRepo = accountClearanceRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<? extends MoveLine> getExcessPayment(AccountClearance accountClearance)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Company company = accountClearance.getCompany();
|
||||||
|
|
||||||
|
this.testCompanyField(company);
|
||||||
|
|
||||||
|
List<? extends MoveLine> moveLineList =
|
||||||
|
moveLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.company = ?1 AND self.account.useForPartnerBalance = 'true' "
|
||||||
|
+ "AND (self.move.statusSelect = ?2 OR self.move.statusSelect = ?3) "
|
||||||
|
+ "AND self.amountRemaining > 0 AND self.amountRemaining <= ?4 AND self.credit > 0 AND self.account in ?5 AND self.date <= ?6",
|
||||||
|
company,
|
||||||
|
MoveRepository.STATUS_VALIDATED,
|
||||||
|
MoveRepository.STATUS_DAYBOOK,
|
||||||
|
accountClearance.getAmountThreshold(),
|
||||||
|
company.getAccountConfig().getClearanceAccountSet(),
|
||||||
|
accountClearance.getDateThreshold())
|
||||||
|
.fetch();
|
||||||
|
|
||||||
|
log.debug("Liste des trop perçus récupérés : {}", moveLineList);
|
||||||
|
|
||||||
|
return moveLineList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void setExcessPayment(AccountClearance accountClearance) throws AxelorException {
|
||||||
|
accountClearance.setMoveLineSet(new HashSet<MoveLine>());
|
||||||
|
List<MoveLine> moveLineList = (List<MoveLine>) this.getExcessPayment(accountClearance);
|
||||||
|
if (moveLineList != null && moveLineList.size() != 0) {
|
||||||
|
accountClearance.getMoveLineSet().addAll(moveLineList);
|
||||||
|
}
|
||||||
|
accountClearanceRepo.save(accountClearance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void validateAccountClearance(AccountClearance accountClearance) throws AxelorException {
|
||||||
|
Company company = accountClearance.getCompany();
|
||||||
|
AccountConfig accountConfig = company.getAccountConfig();
|
||||||
|
|
||||||
|
Tax tax = accountConfig.getStandardRateTax();
|
||||||
|
|
||||||
|
BigDecimal taxRate =
|
||||||
|
taxService.getTaxRate(tax, appBaseService.getTodayDateTime().toLocalDate());
|
||||||
|
Account taxAccount = taxAccountService.getAccount(tax, company, false, false);
|
||||||
|
Account profitAccount = accountConfig.getProfitAccount();
|
||||||
|
Journal journal = accountConfig.getAccountClearanceJournal();
|
||||||
|
|
||||||
|
Set<MoveLine> moveLineList = accountClearance.getMoveLineSet();
|
||||||
|
|
||||||
|
for (MoveLine moveLine : moveLineList) {
|
||||||
|
Move move =
|
||||||
|
this.createAccountClearanceMove(
|
||||||
|
moveLine, taxRate, taxAccount, profitAccount, company, journal, accountClearance);
|
||||||
|
moveService.getMoveValidateService().validate(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
accountClearance.setStatusSelect(AccountClearanceRepository.STATUS_VALIDATED);
|
||||||
|
accountClearance.setDateTime(appBaseService.getTodayDateTime());
|
||||||
|
accountClearance.setName(
|
||||||
|
sequenceService.getSequenceNumber(SequenceRepository.ACCOUNT_CLEARANCE, company));
|
||||||
|
accountClearanceRepo.save(accountClearance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Move createAccountClearanceMove(
|
||||||
|
MoveLine moveLine,
|
||||||
|
BigDecimal taxRate,
|
||||||
|
Account taxAccount,
|
||||||
|
Account profitAccount,
|
||||||
|
Company company,
|
||||||
|
Journal journal,
|
||||||
|
AccountClearance accountClearance)
|
||||||
|
throws AxelorException {
|
||||||
|
Partner partner = moveLine.getPartner();
|
||||||
|
|
||||||
|
// Move
|
||||||
|
Move move =
|
||||||
|
moveService
|
||||||
|
.getMoveCreateService()
|
||||||
|
.createMove(
|
||||||
|
journal, company, null, partner, null, MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
|
||||||
|
// Debit MoveLine 411
|
||||||
|
BigDecimal amount = moveLine.getAmountRemaining();
|
||||||
|
MoveLine debitMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
moveLine.getAccount(),
|
||||||
|
amount,
|
||||||
|
true,
|
||||||
|
appBaseService.getTodayDateTime().toLocalDate(),
|
||||||
|
1,
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
move.getMoveLineList().add(debitMoveLine);
|
||||||
|
|
||||||
|
// Credit MoveLine 77. (profit account)
|
||||||
|
BigDecimal divid = taxRate.add(BigDecimal.ONE);
|
||||||
|
BigDecimal profitAmount =
|
||||||
|
amount
|
||||||
|
.divide(divid, AppBaseService.DEFAULT_NB_DECIMAL_DIGITS, RoundingMode.HALF_EVEN)
|
||||||
|
.setScale(AppBaseService.DEFAULT_NB_DECIMAL_DIGITS, RoundingMode.HALF_EVEN);
|
||||||
|
MoveLine creditMoveLine1 =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
profitAccount,
|
||||||
|
profitAmount,
|
||||||
|
false,
|
||||||
|
appBaseService.getTodayDateTime().toLocalDate(),
|
||||||
|
2,
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
move.getMoveLineList().add(creditMoveLine1);
|
||||||
|
|
||||||
|
// Credit MoveLine 445 (Tax account)
|
||||||
|
BigDecimal taxAmount = amount.subtract(profitAmount);
|
||||||
|
MoveLine creditMoveLine2 =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
taxAccount,
|
||||||
|
taxAmount,
|
||||||
|
false,
|
||||||
|
appBaseService.getTodayDateTime().toLocalDate(),
|
||||||
|
3,
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
move.getMoveLineList().add(creditMoveLine2);
|
||||||
|
|
||||||
|
Reconcile reconcile = reconcileService.createReconcile(debitMoveLine, moveLine, amount, false);
|
||||||
|
if (reconcile != null) {
|
||||||
|
reconcileService.confirmReconcile(reconcile, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
debitMoveLine.setAccountClearance(accountClearance);
|
||||||
|
creditMoveLine1.setAccountClearance(accountClearance);
|
||||||
|
creditMoveLine2.setAccountClearance(accountClearance);
|
||||||
|
return move;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountClearance createAccountClearance(
|
||||||
|
Company company,
|
||||||
|
String name,
|
||||||
|
BigDecimal amountThreshold,
|
||||||
|
LocalDate dateThreshold,
|
||||||
|
List<MoveLine> moveLineSet) {
|
||||||
|
AccountClearance accountClearance = new AccountClearance();
|
||||||
|
accountClearance.setAmountThreshold(amountThreshold);
|
||||||
|
accountClearance.setCompany(company);
|
||||||
|
accountClearance.setDateThreshold(dateThreshold);
|
||||||
|
accountClearance.getMoveLineSet().addAll(moveLineSet);
|
||||||
|
accountClearance.setName(name);
|
||||||
|
accountClearance.setDateTime(appBaseService.getTodayDateTime());
|
||||||
|
accountClearance.setUser(this.user);
|
||||||
|
accountClearance.setStatusSelect(AccountClearanceRepository.STATUS_VALIDATED);
|
||||||
|
return accountClearance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de vérifier les champs d'une société
|
||||||
|
*
|
||||||
|
* @param company Une société
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void testCompanyField(Company company) throws AxelorException {
|
||||||
|
|
||||||
|
AccountConfig accountConfig = company.getAccountConfig();
|
||||||
|
|
||||||
|
if (accountConfig == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CLEARANCE_1),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountConfig.getProfitAccount() == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CLEARANCE_2),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountConfig.getStandardRateTax() == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CLEARANCE_3),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountConfig.getClearanceAccountSet() == null
|
||||||
|
|| accountConfig.getClearanceAccountSet().size() == 0) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CLEARANCE_4),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sequenceService.hasSequence(SequenceRepository.ACCOUNT_CLEARANCE, company)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CLEARANCE_5),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountConfig.getAccountClearanceJournal() == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CLEARANCE_6),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,383 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.AccountingSituation;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountingSituationRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AccountCustomerService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected AccountingSituationService accountingSituationService;
|
||||||
|
protected AccountingSituationRepository accSituationRepo;
|
||||||
|
protected AppBaseService appBaseService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountCustomerService(
|
||||||
|
AccountingSituationService accountingSituationService,
|
||||||
|
AccountingSituationRepository accSituationRepo,
|
||||||
|
AppBaseService appBaseService) {
|
||||||
|
|
||||||
|
this.accountingSituationService = accountingSituationService;
|
||||||
|
this.accSituationRepo = accSituationRepo;
|
||||||
|
this.appBaseService = appBaseService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountingSituationService getAccountingSituationService() {
|
||||||
|
return this.accountingSituationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de calculer le solde total d'un tiers
|
||||||
|
*
|
||||||
|
* @param partner Un tiers
|
||||||
|
* @param company Une société
|
||||||
|
* @return Le solde total
|
||||||
|
*/
|
||||||
|
public BigDecimal getBalance(Partner partner, Company company) {
|
||||||
|
log.debug("Compute balance (Partner : {}, Company : {})", partner.getName(), company.getName());
|
||||||
|
|
||||||
|
Query query =
|
||||||
|
JPA.em()
|
||||||
|
.createNativeQuery(
|
||||||
|
"SELECT SUM(COALESCE(m1.sum_remaining,0) - COALESCE(m2.sum_remaining,0) ) "
|
||||||
|
+ "FROM public.account_move_line AS ml "
|
||||||
|
+ "LEFT OUTER JOIN ( "
|
||||||
|
+ "SELECT moveline.amount_remaining AS sum_remaining, moveline.id AS moveline_id "
|
||||||
|
+ "FROM public.account_move_line AS moveline "
|
||||||
|
+ "WHERE moveline.debit > 0 GROUP BY moveline.id, moveline.amount_remaining) AS m1 ON (m1.moveline_id = ml.id) "
|
||||||
|
+ "LEFT OUTER JOIN ( "
|
||||||
|
+ "SELECT moveline.amount_remaining AS sum_remaining, moveline.id AS moveline_id "
|
||||||
|
+ "FROM public.account_move_line AS moveline "
|
||||||
|
+ "WHERE moveline.credit > 0 GROUP BY moveline.id, moveline.amount_remaining) AS m2 ON (m2.moveline_id = ml.id) "
|
||||||
|
+ "LEFT OUTER JOIN public.account_account AS account ON (ml.account = account.id) "
|
||||||
|
+ "LEFT OUTER JOIN public.account_move AS move ON (ml.move = move.id) "
|
||||||
|
+ "WHERE ml.partner = ?1 AND move.company = ?2 AND move.ignore_in_accounting_ok IN ('false', null)"
|
||||||
|
+ "AND account.use_for_partner_balance = 'true'"
|
||||||
|
+ "AND (move.status_select = ?3 or move.status_select = ?4) AND ml.amount_remaining > 0 ")
|
||||||
|
.setParameter(1, partner)
|
||||||
|
.setParameter(2, company)
|
||||||
|
.setParameter(3, MoveRepository.STATUS_VALIDATED)
|
||||||
|
.setParameter(4, MoveRepository.STATUS_DAYBOOK);
|
||||||
|
|
||||||
|
BigDecimal balance = (BigDecimal) query.getSingleResult();
|
||||||
|
|
||||||
|
if (balance == null) {
|
||||||
|
balance = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Balance : {}", balance);
|
||||||
|
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de calculer le solde exigible d'un tiers
|
||||||
|
*
|
||||||
|
* <p>Calcul du solde exigible du tiers : Montant Total des factures et des échéances rejetées
|
||||||
|
* échues (date du jour >= date de l’échéance)
|
||||||
|
*
|
||||||
|
* @param partner Un tiers
|
||||||
|
* @param company Une société
|
||||||
|
* @return Le solde exigible
|
||||||
|
*/
|
||||||
|
public BigDecimal getBalanceDue(Partner partner, Company company) {
|
||||||
|
log.debug(
|
||||||
|
"Compute balance due (Partner : {}, Company : {})", partner.getName(), company.getName());
|
||||||
|
|
||||||
|
Query query =
|
||||||
|
JPA.em()
|
||||||
|
.createNativeQuery(
|
||||||
|
"SELECT SUM( COALESCE(m1.sum_remaining,0) - COALESCE(m2.sum_remaining,0) ) "
|
||||||
|
+ "FROM public.account_move_line AS ml "
|
||||||
|
+ "LEFT OUTER JOIN ( "
|
||||||
|
+ "SELECT moveline.amount_remaining AS sum_remaining, moveline.id AS moveline_id "
|
||||||
|
+ "FROM public.account_move_line AS moveline "
|
||||||
|
+ "WHERE moveline.debit > 0 "
|
||||||
|
+ "AND ((moveline.due_date IS NULL AND moveline.date_val <= ?1) OR (moveline.due_date IS NOT NULL AND moveline.due_date <= ?1)) "
|
||||||
|
+ "GROUP BY moveline.id, moveline.amount_remaining) AS m1 on (m1.moveline_id = ml.id) "
|
||||||
|
+ "LEFT OUTER JOIN ( "
|
||||||
|
+ "SELECT moveline.amount_remaining AS sum_remaining, moveline.id AS moveline_id "
|
||||||
|
+ "FROM public.account_move_line AS moveline "
|
||||||
|
+ "WHERE moveline.credit > 0 "
|
||||||
|
+ "GROUP BY moveline.id, moveline.amount_remaining) AS m2 ON (m2.moveline_id = ml.id) "
|
||||||
|
+ "LEFT OUTER JOIN public.account_account AS account ON (ml.account = account.id) "
|
||||||
|
+ "LEFT OUTER JOIN public.account_move AS move ON (ml.move = move.id) "
|
||||||
|
+ "WHERE ml.partner = ?2 AND move.company = ?3 AND move.ignore_in_debt_recovery_ok IN ('false', null) "
|
||||||
|
+ "AND move.ignore_in_accounting_ok IN ('false', null) AND account.use_for_partner_balance = 'true'"
|
||||||
|
+ "AND (move.status_select = ?4 OR move.status_select = ?5) AND ml.amount_remaining > 0 ")
|
||||||
|
.setParameter(
|
||||||
|
1,
|
||||||
|
Date.from(
|
||||||
|
appBaseService
|
||||||
|
.getTodayDate()
|
||||||
|
.atStartOfDay()
|
||||||
|
.atZone(ZoneOffset.UTC)
|
||||||
|
.toInstant()),
|
||||||
|
TemporalType.DATE)
|
||||||
|
.setParameter(2, partner)
|
||||||
|
.setParameter(3, company)
|
||||||
|
.setParameter(4, MoveRepository.STATUS_VALIDATED)
|
||||||
|
.setParameter(5, MoveRepository.STATUS_DAYBOOK);
|
||||||
|
|
||||||
|
BigDecimal balance = (BigDecimal) query.getSingleResult();
|
||||||
|
|
||||||
|
if (balance == null) {
|
||||||
|
balance = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Balance due : {}", balance);
|
||||||
|
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **************************************** 2. Calcul du solde exigible (relançable) du tiers
|
||||||
|
* *****************************************
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* solde des factures exigibles non bloquées en relance et dont « la date de facture » + « délai
|
||||||
|
* d’acheminement(X) » <« date du jour » si la date de facture = date d'échéance de facture, sinon
|
||||||
|
* pas de prise en compte du délai d'acheminement **
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* solde des échéances rejetées qui ne sont pas bloqués
|
||||||
|
* *****************************************************
|
||||||
|
*/
|
||||||
|
public BigDecimal getBalanceDueDebtRecovery(Partner partner, Company company) {
|
||||||
|
log.debug(
|
||||||
|
"Compute balance due debt recovery (Partner : {}, Company : {})",
|
||||||
|
partner.getName(),
|
||||||
|
company.getName());
|
||||||
|
|
||||||
|
int mailTransitTime = 0;
|
||||||
|
|
||||||
|
AccountConfig accountConfig = company.getAccountConfig();
|
||||||
|
|
||||||
|
if (accountConfig != null) {
|
||||||
|
mailTransitTime = accountConfig.getMailTransitTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Replace native query to standard JPQL query
|
||||||
|
Query query =
|
||||||
|
JPA.em()
|
||||||
|
.createNativeQuery(
|
||||||
|
"SELECT SUM( COALESCE(m1.sum_remaining,0) - COALESCE(m2.sum_remaining,0) ) "
|
||||||
|
+ "FROM public.account_move_line as ml "
|
||||||
|
+ "LEFT OUTER JOIN ( "
|
||||||
|
+ "SELECT moveline.amount_remaining AS sum_remaining, moveline.id AS moveline_id "
|
||||||
|
+ "FROM public.account_move_line AS moveline "
|
||||||
|
+ "WHERE moveline.debit > 0 AND (( moveline.date_val = moveline.due_date AND (moveline.due_date + ?1 ) < ?2 ) "
|
||||||
|
+ "OR (moveline.due_date IS NOT NULL AND moveline.date_val != moveline.due_date AND moveline.due_date < ?2)"
|
||||||
|
+ "OR (moveline.due_date IS NULL AND moveline.date_val < ?2)) "
|
||||||
|
+ "GROUP BY moveline.id, moveline.amount_remaining) AS m1 ON (m1.moveline_id = ml.id) "
|
||||||
|
+ "LEFT OUTER JOIN ( "
|
||||||
|
+ "SELECT moveline.amount_remaining AS sum_remaining, moveline.id AS moveline_id "
|
||||||
|
+ "FROM public.account_move_line AS moveline "
|
||||||
|
+ "WHERE moveline.credit > 0 "
|
||||||
|
+ "GROUP BY moveline.id, moveline.amount_remaining) AS m2 ON (m2.moveline_id = ml.id) "
|
||||||
|
+ "LEFT OUTER JOIN public.account_account AS account ON (ml.account = account.id) "
|
||||||
|
+ "LEFT OUTER JOIN public.account_move AS move ON (ml.move = move.id) "
|
||||||
|
+ "LEFT JOIN public.account_invoice AS invoice ON (move.invoice = invoice.id) "
|
||||||
|
+ "WHERE ml.partner = ?3 AND move.company = ?4 AND move.ignore_in_debt_recovery_ok in ('false', null) "
|
||||||
|
+ "AND move.ignore_in_accounting_ok IN ('false', null) AND account.use_for_partner_balance = 'true'"
|
||||||
|
+ "AND (move.status_select = ?5 OR move.status_select = ?6) AND ml.amount_remaining > 0 AND invoice.debt_recovery_blocking_ok = FALSE ")
|
||||||
|
.setParameter(1, mailTransitTime)
|
||||||
|
.setParameter(
|
||||||
|
2,
|
||||||
|
Date.from(
|
||||||
|
appBaseService
|
||||||
|
.getTodayDate()
|
||||||
|
.atStartOfDay()
|
||||||
|
.atZone(ZoneOffset.UTC)
|
||||||
|
.toInstant()),
|
||||||
|
TemporalType.DATE)
|
||||||
|
.setParameter(3, partner)
|
||||||
|
.setParameter(4, company)
|
||||||
|
.setParameter(5, MoveRepository.STATUS_VALIDATED)
|
||||||
|
.setParameter(6, MoveRepository.STATUS_DAYBOOK);
|
||||||
|
|
||||||
|
BigDecimal balance = (BigDecimal) query.getSingleResult();
|
||||||
|
|
||||||
|
if (balance == null) {
|
||||||
|
balance = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Balance due debt recovery : {}", balance);
|
||||||
|
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de récupérer l'ensemble des lignes d'écriture pour une société et un tiers
|
||||||
|
*
|
||||||
|
* @param partner Un tiers
|
||||||
|
* @param company Une société
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<? extends MoveLine> getMoveLine(Partner partner, Company company) {
|
||||||
|
|
||||||
|
return Beans.get(MoveLineRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter("self.partner = ?1 AND self.move.company = ?2", partner, company)
|
||||||
|
.fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure mettant à jour les soldes du compte client des tiers pour une société
|
||||||
|
*
|
||||||
|
* @param partnerList Une liste de tiers à mettre à jour
|
||||||
|
* @param company Une société
|
||||||
|
*/
|
||||||
|
public void updatePartnerAccountingSituation(
|
||||||
|
List<Partner> partnerList,
|
||||||
|
Company company,
|
||||||
|
boolean updateCustAccount,
|
||||||
|
boolean updateDueCustAccount,
|
||||||
|
boolean updateDueDebtRecoveryCustAccount)
|
||||||
|
throws AxelorException {
|
||||||
|
for (Partner partner : partnerList) {
|
||||||
|
AccountingSituation accountingSituation =
|
||||||
|
accountingSituationService.getAccountingSituation(partner, company);
|
||||||
|
if (accountingSituation == null) {
|
||||||
|
accountingSituation =
|
||||||
|
accountingSituationService.createAccountingSituation(partner, company);
|
||||||
|
}
|
||||||
|
if (accountingSituation != null) {
|
||||||
|
this.updateAccountingSituationCustomerAccount(
|
||||||
|
accountingSituation,
|
||||||
|
updateCustAccount,
|
||||||
|
updateDueCustAccount,
|
||||||
|
updateDueDebtRecoveryCustAccount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void flagPartners(List<Partner> partnerList, Company company) throws AxelorException {
|
||||||
|
for (Partner partner : partnerList) {
|
||||||
|
AccountingSituation accountingSituation =
|
||||||
|
accountingSituationService.getAccountingSituation(partner, company);
|
||||||
|
if (accountingSituation == null) {
|
||||||
|
accountingSituation =
|
||||||
|
accountingSituationService.createAccountingSituation(partner, company);
|
||||||
|
}
|
||||||
|
if (accountingSituation != null) {
|
||||||
|
accountingSituation.setCustAccountMustBeUpdateOk(true);
|
||||||
|
accSituationRepo.save(accountingSituation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public AccountingSituation updateAccountingSituationCustomerAccount(
|
||||||
|
AccountingSituation accountingSituation,
|
||||||
|
boolean updateCustAccount,
|
||||||
|
boolean updateDueCustAccount,
|
||||||
|
boolean updateDueDebtRecoveryCustAccount)
|
||||||
|
throws AxelorException {
|
||||||
|
Partner partner = accountingSituation.getPartner();
|
||||||
|
Company company = accountingSituation.getCompany();
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Update customer account (Partner : {}, Company : {}, Update balance : {}, balance due : {}, balance due debt recovery : {})",
|
||||||
|
partner.getName(),
|
||||||
|
company.getName(),
|
||||||
|
updateCustAccount,
|
||||||
|
updateDueCustAccount,
|
||||||
|
updateDueDebtRecoveryCustAccount);
|
||||||
|
|
||||||
|
if (updateCustAccount) {
|
||||||
|
accountingSituation.setBalanceCustAccount(this.getBalance(partner, company));
|
||||||
|
}
|
||||||
|
if (updateDueCustAccount) {
|
||||||
|
accountingSituation.setBalanceDueCustAccount(this.getBalanceDue(partner, company));
|
||||||
|
}
|
||||||
|
if (updateDueDebtRecoveryCustAccount) {
|
||||||
|
accountingSituation.setBalanceDueDebtRecoveryCustAccount(
|
||||||
|
this.getBalanceDueDebtRecovery(partner, company));
|
||||||
|
}
|
||||||
|
accountingSituation.setCustAccountMustBeUpdateOk(false);
|
||||||
|
accSituationRepo.save(accountingSituation);
|
||||||
|
|
||||||
|
return accountingSituation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getPartnerAccount(Partner partner, Company company, boolean isSupplierInvoice)
|
||||||
|
throws AxelorException {
|
||||||
|
return isSupplierInvoice
|
||||||
|
? getSupplierAccount(partner, company)
|
||||||
|
: getCustomerAccount(partner, company);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Account getCustomerAccount(Partner partner, Company company) throws AxelorException {
|
||||||
|
Account customerAccount = accountingSituationService.getCustomerAccount(partner, company);
|
||||||
|
|
||||||
|
if (customerAccount == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
partner,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CUSTOMER_1),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return customerAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Account getSupplierAccount(Partner partner, Company company) throws AxelorException {
|
||||||
|
Account supplierAccount = accountingSituationService.getSupplierAccount(partner, company);
|
||||||
|
|
||||||
|
if (supplierAccount == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
partner,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CUSTOMER_2),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return supplierAccount;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AnalyticDistributionTemplate;
|
||||||
|
import com.axelor.apps.account.db.FiscalPosition;
|
||||||
|
import com.axelor.apps.account.db.FixedAssetCategory;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Product;
|
||||||
|
import com.axelor.apps.base.service.tax.AccountManagementService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
|
||||||
|
public interface AccountManagementAccountService extends AccountManagementService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product tax according to the fiscal position
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @param fiscalPosition
|
||||||
|
* @param isPurchase Specify if we want get the tax for purchase or sale
|
||||||
|
* @param fixedAsset Specify if we should get the purchase account for fixed asset or not. Used
|
||||||
|
* only if isPurchase param is true.
|
||||||
|
* @return the tax defined for the product, according to the fiscal position
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public Account getProductAccount(
|
||||||
|
Product product,
|
||||||
|
Company company,
|
||||||
|
FiscalPosition fiscalPosition,
|
||||||
|
boolean isPurchase,
|
||||||
|
boolean fixedAsset)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product analytic distribution template
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public AnalyticDistributionTemplate getAnalyticDistributionTemplate(
|
||||||
|
Product product, Company company);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product fixed asset category
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public FixedAssetCategory getProductFixedAssetCategory(Product product, Company company);
|
||||||
|
}
|
||||||
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountManagement;
|
||||||
|
import com.axelor.apps.account.db.AnalyticDistributionTemplate;
|
||||||
|
import com.axelor.apps.account.db.FiscalPosition;
|
||||||
|
import com.axelor.apps.account.db.FixedAssetCategory;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Product;
|
||||||
|
import com.axelor.apps.base.service.tax.AccountManagementServiceImpl;
|
||||||
|
import com.axelor.apps.base.service.tax.FiscalPositionService;
|
||||||
|
import com.axelor.apps.base.service.tax.TaxService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.meta.CallMethod;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AccountManagementServiceAccountImpl extends AccountManagementServiceImpl
|
||||||
|
implements AccountManagementAccountService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountManagementServiceAccountImpl(
|
||||||
|
FiscalPositionService fiscalPositionService, TaxService taxService) {
|
||||||
|
super(fiscalPositionService, taxService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product tax according to the fiscal position
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @param fiscalPosition
|
||||||
|
* @param isPurchase Specify if we want get the tax for purchase or sale
|
||||||
|
* @param fixedAsset Specify if we should get the purchase account for fixed asset or not. Used
|
||||||
|
* only if isPurchase param is true.
|
||||||
|
* @return the tax defined for the product, according to the fiscal position
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public Account getProductAccount(
|
||||||
|
Product product,
|
||||||
|
Company company,
|
||||||
|
FiscalPosition fiscalPosition,
|
||||||
|
boolean isPurchase,
|
||||||
|
boolean fixedAsset)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Get the account for the product {} (company : {}, purchase : {}, fixed asset : {}, fiscal position : {})",
|
||||||
|
new Object[] {
|
||||||
|
product.getCode(),
|
||||||
|
company.getName(),
|
||||||
|
isPurchase,
|
||||||
|
fixedAsset,
|
||||||
|
fiscalPosition != null ? fiscalPosition.getCode() : null
|
||||||
|
});
|
||||||
|
|
||||||
|
Account generalAccount =
|
||||||
|
this.getProductAccount(product, company, isPurchase, fixedAsset, CONFIG_OBJECT_PRODUCT);
|
||||||
|
|
||||||
|
Account account =
|
||||||
|
new FiscalPositionAccountServiceImpl().getAccount(fiscalPosition, generalAccount);
|
||||||
|
|
||||||
|
if (account != null) {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_MANAGEMENT_1_ACCOUNT),
|
||||||
|
product.getCode(),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product tax
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @param isPurchase
|
||||||
|
* @param fixedAsset Specify if we should get the purchase account for fixed asset or not. Used
|
||||||
|
* only if isPurchase param is true.
|
||||||
|
* @param configObject Specify if we want get the tax from the product or its product family
|
||||||
|
* <li>1 : product
|
||||||
|
* <li>2 : product family
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@CallMethod
|
||||||
|
protected Account getProductAccount(
|
||||||
|
Product product, Company company, boolean isPurchase, boolean fixedAsset, int configObject) {
|
||||||
|
|
||||||
|
AccountManagement accountManagement = this.getAccountManagement(product, company, configObject);
|
||||||
|
|
||||||
|
Account account = null;
|
||||||
|
|
||||||
|
if (accountManagement != null) {
|
||||||
|
if (isPurchase) {
|
||||||
|
if (fixedAsset) {
|
||||||
|
account = accountManagement.getPurchFixedAssetsAccount();
|
||||||
|
} else {
|
||||||
|
account = accountManagement.getPurchaseAccount();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
account = accountManagement.getSaleAccount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account == null && configObject == CONFIG_OBJECT_PRODUCT) {
|
||||||
|
return getProductAccount(
|
||||||
|
product, company, isPurchase, fixedAsset, CONFIG_OBJECT_PRODUCT_FAMILY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product analytic distribution template
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public AnalyticDistributionTemplate getAnalyticDistributionTemplate(
|
||||||
|
Product product, Company company) {
|
||||||
|
|
||||||
|
return getAnalyticDistributionTemplate(product, company, CONFIG_OBJECT_PRODUCT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product analytic distribution template
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param compan
|
||||||
|
* @param configObject Specify if we want get the tax from the product or its product family
|
||||||
|
* <li>1 : product
|
||||||
|
* <li>2 : product family
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
protected AnalyticDistributionTemplate getAnalyticDistributionTemplate(
|
||||||
|
Product product, Company company, int configObject) {
|
||||||
|
|
||||||
|
AccountManagement accountManagement = this.getAccountManagement(product, company, configObject);
|
||||||
|
|
||||||
|
AnalyticDistributionTemplate analyticDistributionTemplate = null;
|
||||||
|
|
||||||
|
if (accountManagement != null) {
|
||||||
|
analyticDistributionTemplate = accountManagement.getAnalyticDistributionTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (analyticDistributionTemplate == null && configObject == CONFIG_OBJECT_PRODUCT) {
|
||||||
|
return getAnalyticDistributionTemplate(product, company, CONFIG_OBJECT_PRODUCT_FAMILY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return analyticDistributionTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product fixed asset category
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public FixedAssetCategory getProductFixedAssetCategory(Product product, Company company) {
|
||||||
|
|
||||||
|
return getProductFixedAssetCategory(product, company, CONFIG_OBJECT_PRODUCT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product fixed asset category
|
||||||
|
*
|
||||||
|
* @param product
|
||||||
|
* @param company
|
||||||
|
* @param configObject Specify if we want get the fixed asset category from the product or its
|
||||||
|
* product family
|
||||||
|
* <li>1 : product
|
||||||
|
* <li>2 : product family
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
protected FixedAssetCategory getProductFixedAssetCategory(
|
||||||
|
Product product, Company company, int configObject) {
|
||||||
|
|
||||||
|
AccountManagement accountManagement = this.getAccountManagement(product, company, configObject);
|
||||||
|
|
||||||
|
FixedAssetCategory fixedAssetCategory = null;
|
||||||
|
|
||||||
|
if (accountManagement != null) {
|
||||||
|
fixedAssetCategory = accountManagement.getFixedAssetCategory();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixedAssetCategory == null && configObject == CONFIG_OBJECT_PRODUCT) {
|
||||||
|
return getProductFixedAssetCategory(product, company, CONFIG_OBJECT_PRODUCT_FAMILY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fixedAssetCategory;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountRepository;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AccountService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
/** Debit balance = debit - credit */
|
||||||
|
public static final Integer BALANCE_TYPE_DEBIT_BALANCE = 1;
|
||||||
|
|
||||||
|
/** Credit balance = credit - debit */
|
||||||
|
public static final Integer BALANCE_TYPE_CREDIT_BALANCE = 2;
|
||||||
|
|
||||||
|
public static final int MAX_LEVEL_OF_ACCOUNT = 20;
|
||||||
|
|
||||||
|
protected AccountRepository accountRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountService(AccountRepository accountRepository) {
|
||||||
|
this.accountRepository = accountRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the balance of the account, depending of the balance type
|
||||||
|
*
|
||||||
|
* @param account Account
|
||||||
|
* @param balanceType
|
||||||
|
* <p>1 : debit balance = debit - credit
|
||||||
|
* <p>2 : credit balance = credit - debit
|
||||||
|
* @return The balance (debit balance or credit balance)
|
||||||
|
*/
|
||||||
|
public BigDecimal computeBalance(Account account, int balanceType) {
|
||||||
|
|
||||||
|
Query balanceQuery =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"select sum(self.debit - self.credit) from MoveLine self where self.account = :account "
|
||||||
|
+ "and self.move.ignoreInAccountingOk IN ('false', null) and self.move.statusSelect IN (2, 3)");
|
||||||
|
|
||||||
|
balanceQuery.setParameter("account", account);
|
||||||
|
|
||||||
|
BigDecimal balance = (BigDecimal) balanceQuery.getSingleResult();
|
||||||
|
|
||||||
|
if (balance != null) {
|
||||||
|
|
||||||
|
if (balanceType == BALANCE_TYPE_CREDIT_BALANCE) {
|
||||||
|
balance = balance.negate();
|
||||||
|
}
|
||||||
|
log.debug("Account balance : {}", balance);
|
||||||
|
|
||||||
|
return balance;
|
||||||
|
} else {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getAllAccountsSubAccountIncluded(List<Long> accountList) {
|
||||||
|
|
||||||
|
return getAllAccountsSubAccountIncluded(accountList, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getAllAccountsSubAccountIncluded(List<Long> accountList, int counter) {
|
||||||
|
|
||||||
|
if (counter > MAX_LEVEL_OF_ACCOUNT) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
List<Long> allAccountsSubAccountIncluded = new ArrayList<>();
|
||||||
|
if (accountList != null && !accountList.isEmpty()) {
|
||||||
|
allAccountsSubAccountIncluded.addAll(accountList);
|
||||||
|
|
||||||
|
for (Long accountId : accountList) {
|
||||||
|
|
||||||
|
allAccountsSubAccountIncluded.addAll(
|
||||||
|
getAllAccountsSubAccountIncluded(getSubAccounts(accountId), counter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allAccountsSubAccountIncluded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getSubAccounts(Long accountId) {
|
||||||
|
|
||||||
|
return accountRepository
|
||||||
|
.all()
|
||||||
|
.filter("self.parentAccount.id = ?1", accountId)
|
||||||
|
.select("id")
|
||||||
|
.fetch(0, 0)
|
||||||
|
.stream()
|
||||||
|
.map(m -> (Long) m.get("id"))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.Year;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
public interface AccountingCloseAnnualService {
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {AxelorException.class, RuntimeException.class})
|
||||||
|
public List<Move> generateCloseAnnualAccount(
|
||||||
|
Year year,
|
||||||
|
Account account,
|
||||||
|
Partner partner,
|
||||||
|
LocalDate endOfYearDate,
|
||||||
|
LocalDate reportedBalanceDate,
|
||||||
|
String origin,
|
||||||
|
String moveDescription,
|
||||||
|
boolean closeYear,
|
||||||
|
boolean openYear,
|
||||||
|
boolean allocatePerPartner)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
public List<Long> getAllAccountOfYear(Set<Account> accountSet, Year year);
|
||||||
|
|
||||||
|
public List<Pair<Long, Long>> assignPartner(
|
||||||
|
List<Long> accountIdList, Year year, boolean allocatePerPartner);
|
||||||
|
}
|
||||||
@ -0,0 +1,373 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveCreateService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveLineService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveValidateService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.Year;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AccountingCloseAnnualServiceImpl implements AccountingCloseAnnualService {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected MoveCreateService moveCreateService;
|
||||||
|
protected MoveLineService moveLineService;
|
||||||
|
protected AccountConfigService accountConfigService;
|
||||||
|
protected MoveRepository moveRepository;
|
||||||
|
protected MoveValidateService moveValidateService;
|
||||||
|
protected ReconcileService reconcileService;
|
||||||
|
protected AccountService accountService;
|
||||||
|
protected AccountRepository accountRepository;
|
||||||
|
protected int counter = 0;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountingCloseAnnualServiceImpl(
|
||||||
|
MoveCreateService moveCreateService,
|
||||||
|
MoveLineService moveLineService,
|
||||||
|
AccountConfigService accountConfigService,
|
||||||
|
MoveRepository moveRepository,
|
||||||
|
MoveValidateService moveValidateService,
|
||||||
|
ReconcileService reconcileService,
|
||||||
|
AccountService accountService,
|
||||||
|
AccountRepository accountRepository) {
|
||||||
|
|
||||||
|
this.moveCreateService = moveCreateService;
|
||||||
|
this.moveLineService = moveLineService;
|
||||||
|
this.accountConfigService = accountConfigService;
|
||||||
|
this.moveRepository = moveRepository;
|
||||||
|
this.moveValidateService = moveValidateService;
|
||||||
|
this.reconcileService = reconcileService;
|
||||||
|
this.accountService = accountService;
|
||||||
|
this.accountRepository = accountRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {AxelorException.class, RuntimeException.class})
|
||||||
|
public List<Move> generateCloseAnnualAccount(
|
||||||
|
Year year,
|
||||||
|
Account account,
|
||||||
|
Partner partner,
|
||||||
|
LocalDate endOfYearDate,
|
||||||
|
LocalDate reportedBalanceDate,
|
||||||
|
String origin,
|
||||||
|
String moveDescription,
|
||||||
|
boolean closeYear,
|
||||||
|
boolean openYear,
|
||||||
|
boolean allocatePerPartner)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
List<Move> moveList = new ArrayList<>();
|
||||||
|
|
||||||
|
Move closeYearMove = null;
|
||||||
|
Move openYearMove = null;
|
||||||
|
|
||||||
|
if (closeYear) {
|
||||||
|
closeYearMove =
|
||||||
|
generateCloseAnnualAccountMove(
|
||||||
|
year,
|
||||||
|
account,
|
||||||
|
endOfYearDate,
|
||||||
|
endOfYearDate,
|
||||||
|
origin,
|
||||||
|
moveDescription,
|
||||||
|
partner,
|
||||||
|
false,
|
||||||
|
allocatePerPartner);
|
||||||
|
|
||||||
|
if (closeYearMove == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
moveList.add(closeYearMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openYear) {
|
||||||
|
openYearMove =
|
||||||
|
generateCloseAnnualAccountMove(
|
||||||
|
year,
|
||||||
|
account,
|
||||||
|
reportedBalanceDate,
|
||||||
|
endOfYearDate,
|
||||||
|
origin,
|
||||||
|
moveDescription,
|
||||||
|
partner,
|
||||||
|
true,
|
||||||
|
allocatePerPartner);
|
||||||
|
|
||||||
|
if (openYearMove == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
moveList.add(openYearMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closeYearMove != null && openYearMove != null) {
|
||||||
|
reconcile(closeYearMove, openYearMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return moveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Move generateCloseAnnualAccountMove(
|
||||||
|
Year year,
|
||||||
|
Account account,
|
||||||
|
LocalDate moveDate,
|
||||||
|
LocalDate originDate,
|
||||||
|
String origin,
|
||||||
|
String moveDescription,
|
||||||
|
Partner partner,
|
||||||
|
boolean isReverse,
|
||||||
|
boolean allocatePerPartner)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Company company = account.getCompany();
|
||||||
|
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
|
||||||
|
BigDecimal balance = computeBalance(year, account, partner, allocatePerPartner);
|
||||||
|
|
||||||
|
if (balance.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer functionalOriginSelect = null;
|
||||||
|
|
||||||
|
if (isReverse) {
|
||||||
|
balance = balance.negate();
|
||||||
|
functionalOriginSelect = MoveRepository.FUNCTIONAL_ORIGIN_OPENING;
|
||||||
|
} else {
|
||||||
|
functionalOriginSelect = MoveRepository.FUNCTIONAL_ORIGIN_CLOSURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Move move =
|
||||||
|
moveCreateService.createMove(
|
||||||
|
accountConfigService.getReportedBalanceJournal(accountConfig),
|
||||||
|
company,
|
||||||
|
company.getCurrency(),
|
||||||
|
partner,
|
||||||
|
moveDate,
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
!isReverse);
|
||||||
|
move.setFunctionalOriginSelect(functionalOriginSelect);
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
this.generateCloseAnnualMoveLine(
|
||||||
|
move, origin, account, moveDescription, originDate, balance.negate());
|
||||||
|
|
||||||
|
this.generateCloseAnnualMoveLine(
|
||||||
|
move,
|
||||||
|
origin,
|
||||||
|
getYearClosureOrOpeningAccount(accountConfig, isReverse),
|
||||||
|
moveDescription,
|
||||||
|
originDate,
|
||||||
|
balance);
|
||||||
|
|
||||||
|
if (move.getMoveLineList() != null && !move.getMoveLineList().isEmpty()) {
|
||||||
|
moveValidateService.validate(move);
|
||||||
|
} else {
|
||||||
|
moveRepository.remove(move);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return move;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Account getYearClosureOrOpeningAccount(AccountConfig accountConfig, boolean isReverse)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
if (isReverse) {
|
||||||
|
return accountConfigService.getYearOpeningAccount(accountConfig);
|
||||||
|
} else {
|
||||||
|
return accountConfigService.getYearClosureAccount(accountConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MoveLine generateCloseAnnualMoveLine(
|
||||||
|
Move move,
|
||||||
|
String origin,
|
||||||
|
Account account,
|
||||||
|
String moveDescription,
|
||||||
|
LocalDate originDate,
|
||||||
|
BigDecimal balance)
|
||||||
|
throws AxelorException {
|
||||||
|
LocalDate moveDate = move.getDate();
|
||||||
|
|
||||||
|
MoveLine moveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
move.getPartner(),
|
||||||
|
account,
|
||||||
|
balance.abs(),
|
||||||
|
balance.abs(),
|
||||||
|
null,
|
||||||
|
balance.compareTo(BigDecimal.ZERO) == 1,
|
||||||
|
moveDate,
|
||||||
|
moveDate,
|
||||||
|
originDate,
|
||||||
|
++counter,
|
||||||
|
origin,
|
||||||
|
moveDescription);
|
||||||
|
|
||||||
|
move.addMoveLineListItem(moveLine);
|
||||||
|
|
||||||
|
return moveLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BigDecimal computeBalance(
|
||||||
|
Year year, Account account, Partner partner, boolean allocatePerPartner) {
|
||||||
|
|
||||||
|
String prepareQuery =
|
||||||
|
"select SUM(self.debit - self.credit) FROM MoveLine as self "
|
||||||
|
+ "WHERE self.move.ignoreInAccountingOk = false AND self.move.period.year = ?1 AND self.account = ?2 "
|
||||||
|
+ "AND self.move.statusSelect = ?3 AND self.move.autoYearClosureMove is not true";
|
||||||
|
|
||||||
|
if (allocatePerPartner && account.getUseForPartnerBalance()) {
|
||||||
|
if (partner != null) {
|
||||||
|
prepareQuery += " AND self.partner = ?4";
|
||||||
|
} else {
|
||||||
|
prepareQuery += " AND self.partner is null";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Query q = JPA.em().createQuery(prepareQuery, BigDecimal.class);
|
||||||
|
q.setParameter(1, year);
|
||||||
|
q.setParameter(2, account);
|
||||||
|
q.setParameter(3, MoveRepository.STATUS_VALIDATED);
|
||||||
|
|
||||||
|
if (partner != null) {
|
||||||
|
q.setParameter(4, partner);
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal result = (BigDecimal) q.getSingleResult();
|
||||||
|
LOG.debug(
|
||||||
|
"Balance : {} for the account : {} and the year : {}",
|
||||||
|
result,
|
||||||
|
account.getCode(),
|
||||||
|
year.getCode());
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reconcile(Move move, Move reverseMove) throws AxelorException {
|
||||||
|
|
||||||
|
List<MoveLine> moveLineSortedList = move.getMoveLineList();
|
||||||
|
Collections.sort(moveLineSortedList, Comparator.comparing(MoveLine::getCounter));
|
||||||
|
|
||||||
|
List<MoveLine> reverseMoveLineSortedList = reverseMove.getMoveLineList();
|
||||||
|
Collections.sort(reverseMoveLineSortedList, Comparator.comparing(MoveLine::getCounter));
|
||||||
|
|
||||||
|
Iterator<MoveLine> reverseMoveLinesIt = reverseMoveLineSortedList.iterator();
|
||||||
|
|
||||||
|
for (MoveLine moveLine : moveLineSortedList) {
|
||||||
|
|
||||||
|
MoveLine reverseMoveLine = reverseMoveLinesIt.next();
|
||||||
|
|
||||||
|
reconcileService.reconcile(moveLine, reverseMoveLine, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getAllAccountOfYear(Set<Account> accountSet, Year year) {
|
||||||
|
|
||||||
|
List<Long> accountIdList =
|
||||||
|
accountService.getAllAccountsSubAccountIncluded(
|
||||||
|
accountSet.stream().map(Account::getId).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
Query q =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"select distinct(self.account.id) FROM MoveLine as self "
|
||||||
|
+ "WHERE self.move.ignoreInAccountingOk = false AND self.move.period.year = ?1 AND self.account.id in (?2) "
|
||||||
|
+ "AND self.move.statusSelect = ?3 AND self.move.autoYearClosureMove is not true",
|
||||||
|
Long.class);
|
||||||
|
q.setParameter(1, year);
|
||||||
|
q.setParameter(2, accountIdList);
|
||||||
|
q.setParameter(3, MoveRepository.STATUS_VALIDATED);
|
||||||
|
|
||||||
|
List<Long> result = q.getResultList();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pair<Long, Long>> assignPartner(
|
||||||
|
List<Long> accountIdList, Year year, boolean allocatePerPartner) {
|
||||||
|
|
||||||
|
List<Pair<Long, Long>> accountAndPartnerPair = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Long accountId : accountIdList) {
|
||||||
|
if (allocatePerPartner && accountRepository.find(accountId).getUseForPartnerBalance()) {
|
||||||
|
for (Long partnerId : getPartner(accountId, year)) {
|
||||||
|
accountAndPartnerPair.add(Pair.of(accountId, partnerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
accountAndPartnerPair.add(Pair.of(accountId, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return accountAndPartnerPair;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Long> getPartner(Long accountId, Year year) {
|
||||||
|
|
||||||
|
Query q =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"select distinct(self.partner.id) FROM MoveLine as self "
|
||||||
|
+ "WHERE self.move.ignoreInAccountingOk = false AND self.move.period.year = ?1 AND self.account.id = ?2 "
|
||||||
|
+ "AND self.move.statusSelect = ?3 AND self.move.autoYearClosureMove is not true",
|
||||||
|
Long.class);
|
||||||
|
q.setParameter(1, year);
|
||||||
|
q.setParameter(2, accountId);
|
||||||
|
q.setParameter(3, MoveRepository.STATUS_VALIDATED);
|
||||||
|
|
||||||
|
List<Long> result = q.getResultList();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountingReport;
|
||||||
|
import com.axelor.apps.account.db.JournalType;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public interface AccountingReportService {
|
||||||
|
|
||||||
|
public String getMoveLineList(AccountingReport accountingReport) throws AxelorException;
|
||||||
|
|
||||||
|
public String buildQuery(AccountingReport accountingReport) throws AxelorException;
|
||||||
|
|
||||||
|
public String addParams(String paramQuery, Object param);
|
||||||
|
|
||||||
|
public String addParams(String paramQuery);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void setSequence(AccountingReport accountingReport, String sequence);
|
||||||
|
|
||||||
|
public String getSequence(AccountingReport accountingReport) throws AxelorException;
|
||||||
|
|
||||||
|
public JournalType getJournalType(AccountingReport accountingReport) throws AxelorException;
|
||||||
|
|
||||||
|
public Account getAccount(AccountingReport accountingReport);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void setStatus(AccountingReport accountingReport);
|
||||||
|
|
||||||
|
/** @param accountingReport */
|
||||||
|
@Transactional
|
||||||
|
public void setPublicationDateTime(AccountingReport accountingReport);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param queryFilter
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public BigDecimal getDebitBalance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param queryFilter
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public BigDecimal getCreditBalance();
|
||||||
|
|
||||||
|
public BigDecimal getDebitBalanceType4();
|
||||||
|
|
||||||
|
public BigDecimal getCreditBalance(AccountingReport accountingReport, String queryFilter);
|
||||||
|
|
||||||
|
public BigDecimal getCreditBalanceType4();
|
||||||
|
|
||||||
|
public String getReportFileLink(AccountingReport accountingReport, String name)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
public boolean isThereTooManyLines(AccountingReport accountingReport) throws AxelorException;
|
||||||
|
|
||||||
|
public void testReportedDateField(LocalDate reportedDate) throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,681 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.ReportFactory;
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.AccountingReport;
|
||||||
|
import com.axelor.apps.account.db.JournalType;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountingReportRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AnalyticMoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.FixedAssetRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentModeRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.TaxPaymentMoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.TaxRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.report.IReport;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountService;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.apps.report.engine.ReportSettings;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import com.axelor.db.Model;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AccountingReportServiceImpl implements AccountingReportService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected AccountingReportRepository accountingReportRepo;
|
||||||
|
|
||||||
|
protected AppBaseService appBaseService;
|
||||||
|
|
||||||
|
protected String query = "";
|
||||||
|
|
||||||
|
protected AccountRepository accountRepo;
|
||||||
|
|
||||||
|
protected List<Object> params = new ArrayList<Object>();
|
||||||
|
protected int paramNumber = 1;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountingReportServiceImpl(
|
||||||
|
AppAccountService appBaseService,
|
||||||
|
AccountingReportRepository accountingReportRepo,
|
||||||
|
AccountRepository accountRepo) {
|
||||||
|
this.accountingReportRepo = accountingReportRepo;
|
||||||
|
this.accountRepo = accountRepo;
|
||||||
|
this.appBaseService = appBaseService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public String getMoveLineList(AccountingReport accountingReport) throws AxelorException {
|
||||||
|
|
||||||
|
this.buildQuery(accountingReport);
|
||||||
|
|
||||||
|
return this.buildDomainFromQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String buildDomainFromQuery() {
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
String domainQuery = this.query;
|
||||||
|
|
||||||
|
for (Object param : params.toArray()) {
|
||||||
|
|
||||||
|
String paramStr = "";
|
||||||
|
if (param instanceof Model) {
|
||||||
|
paramStr = ((Model) param).getId().toString();
|
||||||
|
} else if (param instanceof Set) {
|
||||||
|
Set<Object> paramSet = (Set<Object>) param;
|
||||||
|
for (Object object : paramSet) {
|
||||||
|
if (!paramStr.isEmpty()) {
|
||||||
|
paramStr += ",";
|
||||||
|
}
|
||||||
|
paramStr += ((Model) object).getId().toString();
|
||||||
|
}
|
||||||
|
} else if (param instanceof LocalDate) {
|
||||||
|
paramStr = "'" + param.toString() + "'";
|
||||||
|
} else {
|
||||||
|
paramStr = param.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
domainQuery = domainQuery.replace("?" + i, paramStr);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("domainQuery : {}", domainQuery);
|
||||||
|
return domainQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String buildQuery(AccountingReport accountingReport) throws AxelorException {
|
||||||
|
|
||||||
|
this.initQuery();
|
||||||
|
|
||||||
|
if (accountingReport.getCompany() != null) {
|
||||||
|
this.addParams("self.move.company = ?%d", accountingReport.getCompany());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getCurrency() != null) {
|
||||||
|
this.addParams("self.move.companyCurrency = ?%d", accountingReport.getCurrency());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateFrom() != null) {
|
||||||
|
this.addParams("self.date >= ?%d", accountingReport.getDateFrom());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateTo() != null) {
|
||||||
|
this.addParams("self.date <= ?%d", accountingReport.getDateTo());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDate() != null) {
|
||||||
|
this.addParams("self.date <= ?%d", accountingReport.getDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getJournal() != null) {
|
||||||
|
this.addParams("self.move.journal = ?%d", accountingReport.getJournal());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getPeriod() != null) {
|
||||||
|
this.addParams("self.move.period = ?%d", accountingReport.getPeriod());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getAccountSet() != null && !accountingReport.getAccountSet().isEmpty()) {
|
||||||
|
this.addParams(
|
||||||
|
"(self.account in (?%d) or self.account.parentAccount in (?%d) "
|
||||||
|
+ "or self.account.parentAccount.parentAccount in (?%d) or self.account.parentAccount.parentAccount.parentAccount in (?%d) "
|
||||||
|
+ "or self.account.parentAccount.parentAccount.parentAccount.parentAccount in (?%d) or self.account.parentAccount.parentAccount.parentAccount.parentAccount.parentAccount in (?%d) "
|
||||||
|
+ "or self.account.parentAccount.parentAccount.parentAccount.parentAccount.parentAccount.parentAccount in (?%d))",
|
||||||
|
accountingReport.getAccountSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getPartnerSet() != null && !accountingReport.getPartnerSet().isEmpty()) {
|
||||||
|
this.addParams("self.partner in (?%d)", accountingReport.getPartnerSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getYear() != null) {
|
||||||
|
this.addParams("self.move.period.year = ?%d", accountingReport.getYear());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getPaymentMode() != null) {
|
||||||
|
this.addParams("self.move.paymentMode = ?%d", accountingReport.getPaymentMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_CHEQUE_DEPOSIT) {
|
||||||
|
this.addParams("self.amountPaid > 0 AND self.credit > 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_AGED_BALANCE) {
|
||||||
|
this.addParams("self.account is null or self.account.reconcileOk = 'true'");
|
||||||
|
this.addParams("self.amountRemaining > 0 AND self.debit > 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect()
|
||||||
|
== AccountingReportRepository.REPORT_PARNER_GENERAL_LEDGER) {
|
||||||
|
this.addParams("self.account.useForPartnerBalance = 'true'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_BALANCE) {
|
||||||
|
this.addParams("self.account is null or self.account.reconcileOk = 'true'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_CASH_PAYMENTS) {
|
||||||
|
this.addParams("self.move.paymentMode.typeSelect = ?%d", PaymentModeRepository.TYPE_CASH);
|
||||||
|
this.addParams("self.credit > 0");
|
||||||
|
this.addParams("self.account is null or self.account.reconcileOk = 'true'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_PAYMENT_DIFFERENCES) {
|
||||||
|
this.addParams(
|
||||||
|
"self.account = ?%d",
|
||||||
|
Beans.get((AccountConfigService.class))
|
||||||
|
.getAccountConfig(accountingReport.getCompany())
|
||||||
|
.getCashPositionVariationAccount());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect()
|
||||||
|
== AccountingReportRepository.REPORT_VAT_STATEMENT_INVOICE) {
|
||||||
|
this.addParams("self.taxLine is not null");
|
||||||
|
this.addParams("self.taxLine.tax.typeSelect = ?%d", TaxRepository.TAX_TYPE_DEBIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addParams("self.move.ignoreInAccountingOk = 'false'");
|
||||||
|
|
||||||
|
this.addParams(
|
||||||
|
"(self.move.statusSelect = "
|
||||||
|
+ MoveRepository.STATUS_DAYBOOK
|
||||||
|
+ " OR self.move.statusSelect = "
|
||||||
|
+ MoveRepository.STATUS_VALIDATED
|
||||||
|
+ ")");
|
||||||
|
|
||||||
|
// FOR EXPORT ONLY :
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect()
|
||||||
|
> AccountingReportRepository.EXPORT_PAYROLL_JOURNAL_ENTRY) {
|
||||||
|
this.addParams(
|
||||||
|
"(self.move.accountingOk = false OR (self.move.accountingOk = true and self.move.accountingReport = ?%d))",
|
||||||
|
accountingReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect()
|
||||||
|
>= AccountingReportRepository.EXPORT_PAYROLL_JOURNAL_ENTRY) {
|
||||||
|
this.addParams("self.move.journal.notExportOk = false ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect()
|
||||||
|
> AccountingReportRepository.EXPORT_PAYROLL_JOURNAL_ENTRY) {
|
||||||
|
JournalType journalType = this.getJournalType(accountingReport);
|
||||||
|
if (journalType != null) {
|
||||||
|
this.addParams("self.move.journal.journalType = ?%d", journalType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect() >= AccountingReportRepository.REPORT_PARNER_GENERAL_LEDGER
|
||||||
|
&& accountingReport.getDisplayOnlyNotCompletelyLetteredMoveLines()) {
|
||||||
|
this.addParams("self.amountRemaining > 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Query : {}", this.query);
|
||||||
|
|
||||||
|
return this.query;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initQuery() {
|
||||||
|
query = "";
|
||||||
|
paramNumber = 1;
|
||||||
|
params = new ArrayList<Object>();
|
||||||
|
|
||||||
|
this.query = "";
|
||||||
|
this.params.clear();
|
||||||
|
this.paramNumber = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String addParams(String paramQuery, Object param) {
|
||||||
|
|
||||||
|
log.debug("requete et param : {} : {}", paramQuery, paramNumber);
|
||||||
|
|
||||||
|
this.addParams(paramQuery.replaceAll("%d", String.valueOf(paramNumber++)));
|
||||||
|
this.params.add(param);
|
||||||
|
|
||||||
|
return this.query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String addParams(String paramQuery) {
|
||||||
|
|
||||||
|
if (!this.query.equals("")) {
|
||||||
|
this.query += " AND ";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.query += paramQuery;
|
||||||
|
return this.query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSequence(AccountingReport accountingReport, String sequence) {
|
||||||
|
accountingReport.setRef(sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSequence(AccountingReport accountingReport) throws AxelorException {
|
||||||
|
|
||||||
|
SequenceService sequenceService = Beans.get(SequenceService.class);
|
||||||
|
int accountingReportTypeSelect = accountingReport.getTypeSelect();
|
||||||
|
|
||||||
|
if (accountingReportTypeSelect >= 0 && accountingReportTypeSelect < 1000) {
|
||||||
|
String seq =
|
||||||
|
sequenceService.getSequenceNumber(
|
||||||
|
SequenceRepository.ACCOUNTING_REPORT, accountingReport.getCompany());
|
||||||
|
if (seq == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_REPORT_1),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
accountingReport.getCompany().getName());
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
} else if (accountingReportTypeSelect >= 1000 && accountingReportTypeSelect < 2000) {
|
||||||
|
String seq =
|
||||||
|
sequenceService.getSequenceNumber(
|
||||||
|
SequenceRepository.MOVE_LINE_EXPORT, accountingReport.getCompany());
|
||||||
|
if (seq == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_REPORT_2),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
accountingReport.getCompany().getName());
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
} else if (accountingReportTypeSelect >= 2000 && accountingReportTypeSelect < 3000) {
|
||||||
|
String seq =
|
||||||
|
sequenceService.getSequenceNumber(
|
||||||
|
SequenceRepository.ANALYTIC_REPORT, accountingReport.getCompany());
|
||||||
|
if (seq == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_REPORT_ANALYTIC_REPORT),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
accountingReport.getCompany().getName());
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
throw new AxelorException(
|
||||||
|
accountingReport,
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_REPORT_UNKNOWN_ACCOUNTING_REPORT_TYPE),
|
||||||
|
accountingReport.getTypeSelect());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JournalType getJournalType(AccountingReport accountingReport) throws AxelorException {
|
||||||
|
Company company = accountingReport.getCompany();
|
||||||
|
|
||||||
|
AccountConfigService accountConfigService = Beans.get(AccountConfigService.class);
|
||||||
|
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
|
||||||
|
switch (accountingReport.getTypeSelect()) {
|
||||||
|
case AccountingReportRepository.EXPORT_SALES:
|
||||||
|
return accountConfigService.getSaleJournalType(accountConfig);
|
||||||
|
|
||||||
|
case AccountingReportRepository.EXPORT_REFUNDS:
|
||||||
|
return accountConfigService.getCreditNoteJournalType(accountConfig);
|
||||||
|
|
||||||
|
case AccountingReportRepository.EXPORT_TREASURY:
|
||||||
|
return accountConfigService.getCashJournalType(accountConfig);
|
||||||
|
|
||||||
|
case AccountingReportRepository.EXPORT_PURCHASES:
|
||||||
|
return accountConfigService.getPurchaseJournalType(accountConfig);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAccount(AccountingReport accountingReport) {
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_PAYMENT_DIFFERENCES
|
||||||
|
&& accountingReport.getCompany() != null) {
|
||||||
|
return accountRepo
|
||||||
|
.all()
|
||||||
|
.filter("self.company = ?1 AND self.code LIKE '58%'", accountingReport.getCompany())
|
||||||
|
.fetchOne();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void setStatus(AccountingReport accountingReport) {
|
||||||
|
accountingReport.setStatusSelect(AccountingReportRepository.STATUS_VALIDATED);
|
||||||
|
accountingReportRepo.save(accountingReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param accountingReport */
|
||||||
|
@Transactional
|
||||||
|
public void setPublicationDateTime(AccountingReport accountingReport) {
|
||||||
|
accountingReport.setPublicationDateTime(appBaseService.getTodayDateTime());
|
||||||
|
accountingReportRepo.save(accountingReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param queryFilter
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public BigDecimal getDebitBalance() {
|
||||||
|
|
||||||
|
Query q =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"select SUM(self.debit) FROM MoveLine as self WHERE " + query, BigDecimal.class);
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
for (Object param : params.toArray()) {
|
||||||
|
q.setParameter(i++, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal result = (BigDecimal) q.getSingleResult();
|
||||||
|
log.debug("Total debit : {}", result);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param queryFilter
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public BigDecimal getCreditBalance() {
|
||||||
|
|
||||||
|
Query q =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"select SUM(self.credit) FROM MoveLine as self WHERE " + query, BigDecimal.class);
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
for (Object param : params.toArray()) {
|
||||||
|
q.setParameter(i++, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal result = (BigDecimal) q.getSingleResult();
|
||||||
|
log.debug("Total debit : {}", result);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getDebitBalanceType4() {
|
||||||
|
|
||||||
|
Query q =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"select SUM(self.amountRemaining) FROM MoveLine as self WHERE " + query,
|
||||||
|
BigDecimal.class);
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
for (Object param : params.toArray()) {
|
||||||
|
q.setParameter(i++, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal result = (BigDecimal) q.getSingleResult();
|
||||||
|
log.debug("Total debit : {}", result);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getCreditBalance(AccountingReport accountingReport, String queryFilter) {
|
||||||
|
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_AGED_BALANCE) {
|
||||||
|
return this.getCreditBalanceType4();
|
||||||
|
} else {
|
||||||
|
return this.getCreditBalance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getCreditBalanceType4() {
|
||||||
|
|
||||||
|
return this.getDebitBalance().subtract(this.getDebitBalanceType4());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testReportedDateField(LocalDate reportedDate) throws AxelorException {
|
||||||
|
if (reportedDate == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.CLOSE_NO_REPORTED_BALANCE_DATE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReportFileLink(AccountingReport accountingReport, String name)
|
||||||
|
throws AxelorException {
|
||||||
|
return ReportFactory.createReport(
|
||||||
|
String.format(IReport.ACCOUNTING_REPORT_TYPE, accountingReport.getTypeSelect()),
|
||||||
|
name + "-${date}")
|
||||||
|
.addParam("AccountingReportId", accountingReport.getId())
|
||||||
|
.addParam("Locale", ReportSettings.getPrintingLocale(null))
|
||||||
|
.addFormat(accountingReport.getExportTypeSelect())
|
||||||
|
.toAttach(accountingReport)
|
||||||
|
.generate()
|
||||||
|
.getFileLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isThereTooManyLines(AccountingReport accountingReport) throws AxelorException {
|
||||||
|
|
||||||
|
AccountConfig accountConfig =
|
||||||
|
Beans.get(AccountConfigService.class).getAccountConfig(accountingReport.getCompany());
|
||||||
|
Integer lineMinBeforeLongReportGenerationMessageNumber =
|
||||||
|
accountConfig.getLineMinBeforeLongReportGenerationMessageNumber();
|
||||||
|
if (lineMinBeforeLongReportGenerationMessageNumber != null
|
||||||
|
&& lineMinBeforeLongReportGenerationMessageNumber > 0) {
|
||||||
|
Integer typeSelect = accountingReport.getTypeSelect();
|
||||||
|
long count = 0;
|
||||||
|
if (typeSelect > 0 && typeSelect <= AccountingReportRepository.REPORT_GENERAL_LEDGER2) {
|
||||||
|
count =
|
||||||
|
Beans.get(MoveLineRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter(this.getMoveLineList(accountingReport))
|
||||||
|
.count();
|
||||||
|
} else if (typeSelect == AccountingReportRepository.REPORT_VAT_STATEMENT_RECEIVED) {
|
||||||
|
count =
|
||||||
|
Beans.get(TaxPaymentMoveLineRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter(this.getTaxPaymentMoveLineList(accountingReport))
|
||||||
|
.count();
|
||||||
|
|
||||||
|
} else if (typeSelect == AccountingReportRepository.REPORT_ACQUISITIONS) {
|
||||||
|
count =
|
||||||
|
Beans.get(FixedAssetRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter(this.getFixedAssetList(accountingReport))
|
||||||
|
.count();
|
||||||
|
count +=
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"Select invoiceLine FROM InvoiceLine invoiceLine LEFT JOIN FixedAsset fixedAsset on fixedAsset.invoiceLine = invoiceLine.id WHERE invoiceLine.fixedAssets = true and fixedAsset.invoiceLine is null ")
|
||||||
|
.getResultList()
|
||||||
|
.size();
|
||||||
|
} else if (typeSelect == AccountingReportRepository.REPORT_GROSS_VALUES_AND_DEPRECIATION) {
|
||||||
|
count =
|
||||||
|
Beans.get(FixedAssetRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter(this.getFixedAssetList(accountingReport))
|
||||||
|
.count();
|
||||||
|
} else if (typeSelect == AccountingReportRepository.REPORT_ANALYTIC_BALANCE) {
|
||||||
|
count =
|
||||||
|
Beans.get(AnalyticMoveLineRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter(this.getAnalyticMoveLineList(accountingReport))
|
||||||
|
.count();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return count > lineMinBeforeLongReportGenerationMessageNumber;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getAnalyticMoveLineList(AccountingReport accountingReport) {
|
||||||
|
this.buildAnalyticMoveLineQuery(accountingReport);
|
||||||
|
return this.buildDomainFromQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildAnalyticMoveLineQuery(AccountingReport accountingReport) {
|
||||||
|
this.initQuery();
|
||||||
|
|
||||||
|
this.addParams("self.moveLine.move.companyCurrency = ?%d", accountingReport.getCurrency());
|
||||||
|
|
||||||
|
if (accountingReport.getJournal() != null) {
|
||||||
|
this.addParams("self.moveLine.move.journal = ?%d", accountingReport.getJournal());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateFrom() != null) {
|
||||||
|
this.addParams("self.date >= ?%d", accountingReport.getDateFrom());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateTo() != null) {
|
||||||
|
this.addParams("self.date <= ?%d", accountingReport.getDateTo());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addParams("self.date <= ?%d", accountingReport.getDate());
|
||||||
|
|
||||||
|
if (accountingReport.getAnalyticJournal() != null) {
|
||||||
|
this.addParams("self.analyticJournal = ?%d", accountingReport.getAnalyticJournal());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addParams("self.typeSelect = ?%d", AnalyticMoveLineRepository.STATUS_REAL_ACCOUNTING);
|
||||||
|
|
||||||
|
this.addParams("self.moveLine.move.ignoreInAccountingOk = 'false'");
|
||||||
|
|
||||||
|
this.addParams(
|
||||||
|
"(self.moveLine.move.statusSelect = "
|
||||||
|
+ MoveRepository.STATUS_DAYBOOK
|
||||||
|
+ " OR self.moveLine.move.statusSelect = "
|
||||||
|
+ MoveRepository.STATUS_VALIDATED
|
||||||
|
+ ")");
|
||||||
|
|
||||||
|
log.debug("Query : {}", this.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getFixedAssetList(AccountingReport accountingReport) {
|
||||||
|
this.buildFixedAssetQuery(accountingReport);
|
||||||
|
return this.buildDomainFromQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void buildFixedAssetQuery(AccountingReport accountingReport) {
|
||||||
|
this.initQuery();
|
||||||
|
this.addParams(
|
||||||
|
"(self.statusSelect = "
|
||||||
|
+ FixedAssetRepository.STATUS_VALIDATED
|
||||||
|
+ " OR self.statusSelect = "
|
||||||
|
+ FixedAssetRepository.STATUS_DEPRECIATED
|
||||||
|
+ ")");
|
||||||
|
if (accountingReport.getTypeSelect() == AccountingReportRepository.REPORT_ACQUISITIONS) {
|
||||||
|
if (accountingReport.getDateFrom() != null) {
|
||||||
|
this.addParams("self.acquisitionDate >= ?%d", accountingReport.getDateFrom());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateTo() != null) {
|
||||||
|
this.addParams("self.acquisitionDate <= ?%d", accountingReport.getDateTo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (accountingReport.getTypeSelect()
|
||||||
|
== AccountingReportRepository.REPORT_GROSS_VALUES_AND_DEPRECIATION) {
|
||||||
|
this.query += " OR ( self.statusSelect = " + FixedAssetRepository.STATUS_TRANSFERRED + " ";
|
||||||
|
if (accountingReport.getDateFrom() != null) {
|
||||||
|
this.addParams("self.disposalDate >= ?%d", accountingReport.getDateFrom());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateTo() != null) {
|
||||||
|
this.addParams("self.disposalDate <= ?%d", accountingReport.getDateTo());
|
||||||
|
}
|
||||||
|
this.query += " ) ";
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Query : {}", this.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getTaxPaymentMoveLineList(AccountingReport accountingReport) {
|
||||||
|
this.buildTaxPaymentQuery(accountingReport);
|
||||||
|
|
||||||
|
return this.buildDomainFromQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String buildTaxPaymentQuery(AccountingReport accountingReport) {
|
||||||
|
this.initQuery();
|
||||||
|
|
||||||
|
if (accountingReport.getCompany() != null) {
|
||||||
|
this.addParams("self.moveLine.move.company = ?%d", accountingReport.getCompany());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getCurrency() != null) {
|
||||||
|
this.addParams("self.moveLine.move.companyCurrency = ?%d", accountingReport.getCurrency());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateFrom() != null) {
|
||||||
|
this.addParams("self.moveLine.date >= ?%d", accountingReport.getDateFrom());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountingReport.getDateTo() != null) {
|
||||||
|
this.addParams("self.moveLine.date <= ?%d", accountingReport.getDateTo());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addParams("self.moveLine.move.ignoreInAccountingOk = 'false'");
|
||||||
|
|
||||||
|
this.addParams(
|
||||||
|
"(self.moveLine.move.statusSelect = "
|
||||||
|
+ MoveRepository.STATUS_DAYBOOK
|
||||||
|
+ " OR self.moveLine.move.statusSelect = "
|
||||||
|
+ MoveRepository.STATUS_VALIDATED
|
||||||
|
+ ")");
|
||||||
|
|
||||||
|
this.addParams("self.originTaxLine.tax.typeSelect = ?%d", TaxRepository.TAX_TYPE_COLLECTION);
|
||||||
|
|
||||||
|
log.debug("Query : {}", this.query);
|
||||||
|
return this.query;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
public class AccountingService {
|
||||||
|
|
||||||
|
private static boolean DEFAULT_UPDATE_CUSTOMER_ACCOUNT = true;
|
||||||
|
|
||||||
|
private static final ThreadLocal<Boolean> threadLocal = new ThreadLocal<Boolean>();
|
||||||
|
|
||||||
|
public static void setUpdateCustomerAccount(boolean updateCustomerAccount) {
|
||||||
|
|
||||||
|
threadLocal.set(updateCustomerAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean getUpdateCustomerAccount() {
|
||||||
|
|
||||||
|
if (threadLocal.get() != null) {
|
||||||
|
return threadLocal.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_UPDATE_CUSTOMER_ACCOUNT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountingSituation;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.meta.CallMethod;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface AccountingSituationService {
|
||||||
|
|
||||||
|
boolean checkAccountingSituationList(
|
||||||
|
List<AccountingSituation> accountingSituationList, Company company);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates unexisting accounting situations for a given partner. Created situations will be
|
||||||
|
* appended to the partner's AccountingSituationList
|
||||||
|
*
|
||||||
|
* @param partner Partner to create accounting situation for.
|
||||||
|
* @return The created accounting situations (which is the same as calling
|
||||||
|
* partner.getAccountingSituationList())
|
||||||
|
* @throws AxelorException In case of configuration issue
|
||||||
|
*/
|
||||||
|
List<AccountingSituation> createAccountingSituation(Partner partner) throws AxelorException;
|
||||||
|
|
||||||
|
AccountingSituation getAccountingSituation(Partner partner, Company company);
|
||||||
|
|
||||||
|
AccountingSituation createAccountingSituation(Partner partner, Company company)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically creates supplier/customer/employee accounts based on situation's company
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* @param situation Situation on which accounts should be created.
|
||||||
|
*/
|
||||||
|
void createPartnerAccounts(AccountingSituation situation) throws AxelorException;
|
||||||
|
|
||||||
|
String createDomainForBankDetails(
|
||||||
|
AccountingSituation accountingSituation, boolean isInBankDetails);
|
||||||
|
|
||||||
|
void updateCustomerCredit(Partner partner) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get customer account from accounting situation or account config.
|
||||||
|
*
|
||||||
|
* @param partner
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Account getCustomerAccount(Partner partner, Company company) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get supplier account from accounting situation or account config.
|
||||||
|
*
|
||||||
|
* @param partner
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Account getSupplierAccount(Partner partner, Company company) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get employee account from accounting situation or account config.
|
||||||
|
*
|
||||||
|
* @param partner
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Account getEmployeeAccount(Partner partner, Company company) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return bank details for sales to <code>partner</code> (took from SaleOrder.xml).
|
||||||
|
*
|
||||||
|
* @param company
|
||||||
|
* @param partner
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@CallMethod
|
||||||
|
BankDetails getCompanySalesBankDetails(Company company, Partner partner);
|
||||||
|
}
|
||||||
@ -0,0 +1,496 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.AccountType;
|
||||||
|
import com.axelor.apps.account.db.AccountingSituation;
|
||||||
|
import com.axelor.apps.account.db.PaymentMode;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountConfigRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountTypeRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.AccountingSituationRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountService;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentModeService;
|
||||||
|
import com.axelor.apps.base.db.AppAccount;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.Sequence;
|
||||||
|
import com.axelor.apps.base.db.repo.AppAccountRepository;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.apps.tool.StringTool;
|
||||||
|
import com.axelor.common.StringUtils;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class AccountingSituationServiceImpl implements AccountingSituationService {
|
||||||
|
|
||||||
|
protected AccountConfigService accountConfigService;
|
||||||
|
protected SequenceService sequenceService;
|
||||||
|
protected AccountingSituationRepository accountingSituationRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AccountingSituationServiceImpl(
|
||||||
|
AccountConfigService accountConfigService,
|
||||||
|
SequenceService sequenceService,
|
||||||
|
AccountingSituationRepository accountingSituationRepo) {
|
||||||
|
this.accountConfigService = accountConfigService;
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
this.accountingSituationRepo = accountingSituationRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkAccountingSituationList(
|
||||||
|
List<AccountingSituation> accountingSituationList, Company company) {
|
||||||
|
|
||||||
|
if (accountingSituationList != null) {
|
||||||
|
for (AccountingSituation accountingSituation : accountingSituationList) {
|
||||||
|
|
||||||
|
if (accountingSituation.getCompany().equals(company)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public List<AccountingSituation> createAccountingSituation(Partner partner)
|
||||||
|
throws AxelorException {
|
||||||
|
Set<Company> companySet = partner.getCompanySet();
|
||||||
|
|
||||||
|
if (companySet != null) {
|
||||||
|
for (Company company : companySet) {
|
||||||
|
if (!checkAccountingSituationList(partner.getAccountingSituationList(), company)) {
|
||||||
|
createAccountingSituation(partner, company);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return partner.getAccountingSituationList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public AccountingSituation createAccountingSituation(Partner partner, Company company)
|
||||||
|
throws AxelorException {
|
||||||
|
AccountingSituation accountingSituation = new AccountingSituation();
|
||||||
|
accountingSituation.setCompany(company);
|
||||||
|
partner.addCompanySetItem(company);
|
||||||
|
|
||||||
|
PaymentMode inPaymentMode = partner.getInPaymentMode();
|
||||||
|
PaymentMode outPaymentMode = partner.getOutPaymentMode();
|
||||||
|
BankDetails defaultBankDetails = company.getDefaultBankDetails();
|
||||||
|
|
||||||
|
if (inPaymentMode != null) {
|
||||||
|
List<BankDetails> authorizedInBankDetails =
|
||||||
|
Beans.get(PaymentModeService.class).getCompatibleBankDetailsList(inPaymentMode, company);
|
||||||
|
if (authorizedInBankDetails.contains(defaultBankDetails)) {
|
||||||
|
accountingSituation.setCompanyInBankDetails(defaultBankDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outPaymentMode != null) {
|
||||||
|
List<BankDetails> authorizedOutBankDetails =
|
||||||
|
Beans.get(PaymentModeService.class).getCompatibleBankDetailsList(outPaymentMode, company);
|
||||||
|
if (authorizedOutBankDetails.contains(defaultBankDetails)) {
|
||||||
|
accountingSituation.setCompanyOutBankDetails(defaultBankDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Account acc = this.createPartnerAccount(partner, company);
|
||||||
|
AccountConfig accountConfig = Beans.get(AccountConfigService.class).getAccountConfig(company);
|
||||||
|
accountingSituation.setInvoiceAutomaticMail(accountConfig.getInvoiceAutomaticMail());
|
||||||
|
accountingSituation.setInvoiceMessageTemplate(accountConfig.getInvoiceMessageTemplate());
|
||||||
|
|
||||||
|
if (acc != null) {
|
||||||
|
if (partner.getIsCustomer()) {
|
||||||
|
accountingSituation.setCustomerAccount(acc);
|
||||||
|
} else if (partner.getIsSupplier()) {
|
||||||
|
accountingSituation.setSupplierAccount(acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partner.addAccountingSituationListItem(accountingSituation);
|
||||||
|
return accountingSituationRepo.save(accountingSituation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sophal creating account
|
||||||
|
@Transactional
|
||||||
|
private Account createPartnerAccount(Partner partner, Company company) {
|
||||||
|
Account sAccount = new Account();
|
||||||
|
AppAccount appAccount = Beans.get(AppAccountService.class).getAppAccount();
|
||||||
|
int partnerCode = appAccount.getSupplierCodeSequence() + 1;
|
||||||
|
appAccount.setSupplierCodeSequence(partnerCode);
|
||||||
|
|
||||||
|
String accounString = "Fournisseurs";
|
||||||
|
if (partner.getIsCustomer()) {
|
||||||
|
accounString = "Clients";
|
||||||
|
partnerCode = appAccount.getClientCodeSequence() + 1;
|
||||||
|
appAccount.setClientCodeSequence(partnerCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountType accountType = Beans.get(AccountTypeRepository.class).findByName(accounString);
|
||||||
|
Account parenAccount = Beans.get(AccountRepository.class).findByCode("0");
|
||||||
|
|
||||||
|
sAccount.setAccountType(accountType);
|
||||||
|
sAccount.setCode(String.valueOf(partnerCode));
|
||||||
|
sAccount.setName(partner.getName());
|
||||||
|
sAccount.setReconcileOk(true);
|
||||||
|
sAccount.setUseForPartnerBalance(true);
|
||||||
|
sAccount.setCompany(company);
|
||||||
|
sAccount.setParentAccount(parenAccount);
|
||||||
|
|
||||||
|
Beans.get(AppAccountRepository.class).save(appAccount);
|
||||||
|
|
||||||
|
return sAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccountingSituation getAccountingSituation(Partner partner, Company company) {
|
||||||
|
if (partner == null || partner.getAccountingSituationList() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AccountingSituation accountingSituation : partner.getAccountingSituationList()) {
|
||||||
|
if (accountingSituation.getCompany() != null
|
||||||
|
&& accountingSituation.getCompany().equals(company)) {
|
||||||
|
return accountingSituation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void createPartnerAccounts(AccountingSituation situation) throws AxelorException {
|
||||||
|
AccountConfig accountConfig = situation.getCompany().getAccountConfig();
|
||||||
|
int creationMode;
|
||||||
|
if (accountConfig == null
|
||||||
|
|| (creationMode = accountConfig.getPartnerAccountGenerationModeSelect())
|
||||||
|
== AccountConfigRepository.AUTOMATIC_ACCOUNT_CREATION_NONE) {
|
||||||
|
// Ignore even if account config is null since this means no automatic creation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
createCustomerAccount(accountConfig, situation, creationMode);
|
||||||
|
createSupplierAccount(accountConfig, situation, creationMode);
|
||||||
|
createEmployeeAccount(accountConfig, situation, creationMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createCustomerAccount(
|
||||||
|
AccountConfig accountConfig, AccountingSituation situation, int creationMode)
|
||||||
|
throws AxelorException {
|
||||||
|
Partner partner = situation.getPartner();
|
||||||
|
if (partner.getIsCustomer() == Boolean.FALSE || situation.getCustomerAccount() != null) return;
|
||||||
|
|
||||||
|
if (accountConfig.getCustomerAccount() == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
partner,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CUSTOMER_1),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String accountCode;
|
||||||
|
if (creationMode == AccountConfigRepository.AUTOMATIC_ACCOUNT_CREATION_PREFIX) {
|
||||||
|
final String prefix = accountConfig.getCustomerAccountPrefix();
|
||||||
|
if (StringUtils.isBlank(prefix)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_1),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
accountCode = getPrefixedAccountCode(prefix, partner);
|
||||||
|
} else if (creationMode == AccountConfigRepository.AUTOMATIC_ACCOUNT_CREATION_SEQUENCE) {
|
||||||
|
final Sequence sequence = accountConfig.getCustomerAccountSequence();
|
||||||
|
if (sequence == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_2),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
accountCode = sequenceService.getSequenceNumber(sequence);
|
||||||
|
} else {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_3),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Account account = new Account();
|
||||||
|
account.setName(partner.getFullName());
|
||||||
|
account.setCode(accountCode);
|
||||||
|
account.setParentAccount(accountConfig.getCustomerAccount());
|
||||||
|
account.setAccountType(accountConfig.getCustomerAccount().getAccountType());
|
||||||
|
account.setReconcileOk(true);
|
||||||
|
account.setCompany(situation.getCompany());
|
||||||
|
account.setUseForPartnerBalance(true);
|
||||||
|
account.setCompatibleAccountSet(new HashSet<>());
|
||||||
|
situation.setCustomerAccount(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createSupplierAccount(
|
||||||
|
AccountConfig accountConfig, AccountingSituation situation, int creationMode)
|
||||||
|
throws AxelorException {
|
||||||
|
Partner partner = situation.getPartner();
|
||||||
|
if (partner.getIsSupplier() == Boolean.FALSE || situation.getSupplierAccount() != null) return;
|
||||||
|
|
||||||
|
if (accountConfig.getSupplierAccount() == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
partner,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CUSTOMER_2),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String accountCode;
|
||||||
|
if (creationMode == AccountConfigRepository.AUTOMATIC_ACCOUNT_CREATION_PREFIX) {
|
||||||
|
final String prefix = accountConfig.getSupplierAccountPrefix();
|
||||||
|
if (StringUtils.isBlank(prefix)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_4),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
accountCode = getPrefixedAccountCode(prefix, partner);
|
||||||
|
|
||||||
|
} else if (creationMode == AccountConfigRepository.AUTOMATIC_ACCOUNT_CREATION_SEQUENCE) {
|
||||||
|
final Sequence sequence = accountConfig.getSupplierAccountSequence();
|
||||||
|
if (sequence == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_5),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
accountCode = sequenceService.getSequenceNumber(sequence);
|
||||||
|
} else {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_3),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Account account = new Account();
|
||||||
|
account.setName(partner.getFullName());
|
||||||
|
account.setCode(accountCode);
|
||||||
|
account.setParentAccount(accountConfig.getSupplierAccount());
|
||||||
|
account.setAccountType(accountConfig.getSupplierAccount().getAccountType());
|
||||||
|
account.setReconcileOk(true);
|
||||||
|
account.setCompany(situation.getCompany());
|
||||||
|
account.setUseForPartnerBalance(true);
|
||||||
|
account.setCompatibleAccountSet(new HashSet<>());
|
||||||
|
situation.setSupplierAccount(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createEmployeeAccount(
|
||||||
|
AccountConfig accountConfig, AccountingSituation situation, int creationMode)
|
||||||
|
throws AxelorException {
|
||||||
|
Partner partner = situation.getPartner();
|
||||||
|
if (partner.getIsEmployee() == Boolean.FALSE || situation.getEmployeeAccount() != null) return;
|
||||||
|
|
||||||
|
if (accountConfig.getEmployeeAccount() == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
partner,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNT_CONFIG_40),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String accountCode;
|
||||||
|
if (creationMode == AccountConfigRepository.AUTOMATIC_ACCOUNT_CREATION_PREFIX) {
|
||||||
|
final String prefix = accountConfig.getEmployeeAccountPrefix();
|
||||||
|
if (StringUtils.isBlank(prefix)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_6),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
accountCode = getPrefixedAccountCode(prefix, partner);
|
||||||
|
} else if (creationMode == AccountConfigRepository.AUTOMATIC_ACCOUNT_CREATION_SEQUENCE) {
|
||||||
|
final Sequence sequence = accountConfig.getEmployeeAccountSequence();
|
||||||
|
if (sequence == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_7),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
accountCode = sequenceService.getSequenceNumber(sequence);
|
||||||
|
} else {
|
||||||
|
throw new AxelorException(
|
||||||
|
situation,
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.ACCOUNTING_SITUATION_3),
|
||||||
|
situation.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Account account = new Account();
|
||||||
|
account.setName(partner.getFullName());
|
||||||
|
account.setCode(accountCode);
|
||||||
|
account.setParentAccount(accountConfig.getEmployeeAccount());
|
||||||
|
account.setAccountType(accountConfig.getEmployeeAccount().getAccountType());
|
||||||
|
account.setReconcileOk(true);
|
||||||
|
account.setCompany(situation.getCompany());
|
||||||
|
account.setUseForPartnerBalance(true);
|
||||||
|
account.setCompatibleAccountSet(new HashSet<>());
|
||||||
|
situation.setEmployeeAccount(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize partner's fullname to be usable as an account name. Name is appended to prefix, then
|
||||||
|
* uppercased and unaccented
|
||||||
|
*
|
||||||
|
* @param prefix Prefix to prepend to the generated account code
|
||||||
|
* @param partner Partner to generate account code for
|
||||||
|
* @return The generated account code.
|
||||||
|
*/
|
||||||
|
protected String getPrefixedAccountCode(String prefix, Partner partner) {
|
||||||
|
return (prefix + StringUtils.stripAccent(partner.getFullName()))
|
||||||
|
.toUpperCase()
|
||||||
|
.replaceAll("[^A-Z]", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the domain for the bank details in Accounting Situation
|
||||||
|
*
|
||||||
|
* @param accountingSituation
|
||||||
|
* @param isInBankDetails true if the field is companyInBankDetails false if the field is
|
||||||
|
* companyOutBankDetails
|
||||||
|
* @return the domain of the bank details field
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String createDomainForBankDetails(
|
||||||
|
AccountingSituation accountingSituation, boolean isInBankDetails) {
|
||||||
|
String domain = "";
|
||||||
|
List<BankDetails> authorizedBankDetails;
|
||||||
|
if (accountingSituation.getPartner() != null) {
|
||||||
|
|
||||||
|
if (isInBankDetails) {
|
||||||
|
authorizedBankDetails =
|
||||||
|
Beans.get(PaymentModeService.class)
|
||||||
|
.getCompatibleBankDetailsList(
|
||||||
|
accountingSituation.getPartner().getInPaymentMode(),
|
||||||
|
accountingSituation.getCompany());
|
||||||
|
} else {
|
||||||
|
authorizedBankDetails =
|
||||||
|
Beans.get(PaymentModeService.class)
|
||||||
|
.getCompatibleBankDetailsList(
|
||||||
|
accountingSituation.getPartner().getOutPaymentMode(),
|
||||||
|
accountingSituation.getCompany());
|
||||||
|
}
|
||||||
|
String idList = StringTool.getIdListString(authorizedBankDetails);
|
||||||
|
if (idList.equals("")) {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
domain = "self.id IN (" + idList + ") AND self.active = true";
|
||||||
|
}
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateCustomerCredit(Partner partner) throws AxelorException {
|
||||||
|
// Nothing to do if the supplychain module is not loaded.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account getCustomerAccount(Partner partner, Company company) throws AxelorException {
|
||||||
|
Account account = null;
|
||||||
|
AccountingSituation accountingSituation = getAccountingSituation(partner, company);
|
||||||
|
|
||||||
|
if (accountingSituation != null) {
|
||||||
|
account = accountingSituation.getCustomerAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account == null) {
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
account = accountConfigService.getCustomerAccount(accountConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account getSupplierAccount(Partner partner, Company company) throws AxelorException {
|
||||||
|
Account account = null;
|
||||||
|
AccountingSituation accountingSituation = getAccountingSituation(partner, company);
|
||||||
|
|
||||||
|
if (accountingSituation != null) {
|
||||||
|
account = accountingSituation.getSupplierAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account == null) {
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
account = accountConfigService.getSupplierAccount(accountConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account getEmployeeAccount(Partner partner, Company company) throws AxelorException {
|
||||||
|
Account account = null;
|
||||||
|
AccountingSituation accountingSituation = getAccountingSituation(partner, company);
|
||||||
|
|
||||||
|
if (accountingSituation != null) {
|
||||||
|
account = accountingSituation.getEmployeeAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account == null) {
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
account = accountConfigService.getEmployeeAccount(accountConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BankDetails getCompanySalesBankDetails(Company company, Partner partner) {
|
||||||
|
AccountingSituation situation = getAccountingSituation(partner, company);
|
||||||
|
if (situation != null
|
||||||
|
&& situation.getCompanyInBankDetails() != null
|
||||||
|
&& situation.getCompanyInBankDetails().getActive()) {
|
||||||
|
return situation.getCompanyInBankDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
return company.getDefaultBankDetails();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.Umr;
|
||||||
|
import com.axelor.apps.base.service.AddressServiceImpl;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
|
||||||
|
public class AddressServiceAccountImpl extends AddressServiceImpl {
|
||||||
|
static {
|
||||||
|
registerCheckUsedFunc(AddressServiceAccountImpl::checkAddressUsedAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkAddressUsedAccount(Long addressId) {
|
||||||
|
return JPA.all(Invoice.class).filter("self.address.id = ?1", addressId).fetchOne() != null
|
||||||
|
|| JPA.all(Umr.class).filter("self.debtorAddress.id = ?1", addressId).fetchOne() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AnalyticDistributionLine;
|
||||||
|
import com.axelor.apps.account.db.AnalyticDistributionTemplate;
|
||||||
|
import com.axelor.apps.account.db.AnalyticMoveLine;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.Product;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface AnalyticMoveLineService {
|
||||||
|
public BigDecimal computeAmount(AnalyticMoveLine analyticMoveLine);
|
||||||
|
|
||||||
|
public List<AnalyticMoveLine> generateLines(
|
||||||
|
AnalyticDistributionTemplate analyticDistributionTemplate,
|
||||||
|
BigDecimal total,
|
||||||
|
int typeSelect,
|
||||||
|
LocalDate date);
|
||||||
|
|
||||||
|
public AnalyticDistributionTemplate getAnalyticDistributionTemplate(
|
||||||
|
Partner partner, Product product, Company company);
|
||||||
|
|
||||||
|
public void updateAnalyticMoveLine(
|
||||||
|
AnalyticMoveLine analyticMoveLine, BigDecimal total, LocalDate date);
|
||||||
|
|
||||||
|
public boolean validateLines(List<AnalyticDistributionLine> analyticDistributionLineList);
|
||||||
|
}
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AnalyticAxis;
|
||||||
|
import com.axelor.apps.account.db.AnalyticDistributionLine;
|
||||||
|
import com.axelor.apps.account.db.AnalyticDistributionTemplate;
|
||||||
|
import com.axelor.apps.account.db.AnalyticJournal;
|
||||||
|
import com.axelor.apps.account.db.AnalyticMoveLine;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountService;
|
||||||
|
import com.axelor.apps.base.db.AppAccount;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.Product;
|
||||||
|
import com.axelor.apps.base.db.repo.AppAccountRepository;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AnalyticMoveLineServiceImpl implements AnalyticMoveLineService {
|
||||||
|
|
||||||
|
protected AppAccountService appAccountService;
|
||||||
|
protected AccountManagementServiceAccountImpl accountManagementServiceAccountImpl;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AnalyticMoveLineServiceImpl(
|
||||||
|
AppAccountService appAccountService,
|
||||||
|
AccountManagementServiceAccountImpl accountManagementServiceAccountImpl) {
|
||||||
|
|
||||||
|
this.appAccountService = appAccountService;
|
||||||
|
this.accountManagementServiceAccountImpl = accountManagementServiceAccountImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal computeAmount(AnalyticMoveLine analyticMoveLine) {
|
||||||
|
|
||||||
|
return analyticMoveLine
|
||||||
|
.getPercentage()
|
||||||
|
.multiply(analyticMoveLine.getOriginalPieceAmount())
|
||||||
|
.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AnalyticMoveLine> generateLines(
|
||||||
|
AnalyticDistributionTemplate analyticDistributionTemplate,
|
||||||
|
BigDecimal total,
|
||||||
|
int typeSelect,
|
||||||
|
LocalDate date) {
|
||||||
|
|
||||||
|
List<AnalyticMoveLine> analyticMoveLineList = new ArrayList<AnalyticMoveLine>();
|
||||||
|
if (analyticDistributionTemplate != null) {
|
||||||
|
for (AnalyticDistributionLine analyticDistributionLine :
|
||||||
|
analyticDistributionTemplate.getAnalyticDistributionLineList()) {
|
||||||
|
analyticMoveLineList.add(
|
||||||
|
this.createAnalyticMoveLine(analyticDistributionLine, total, typeSelect, date));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return analyticMoveLineList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnalyticDistributionTemplate getAnalyticDistributionTemplate(
|
||||||
|
Partner partner, Product product, Company company) {
|
||||||
|
|
||||||
|
AppAccount appAccount = appAccountService.getAppAccount();
|
||||||
|
|
||||||
|
if (appAccount.getAnalyticDistributionTypeSelect()
|
||||||
|
== AppAccountRepository.DISTRIBUTION_TYPE_PARTNER
|
||||||
|
&& partner != null) {
|
||||||
|
return partner.getAnalyticDistributionTemplate();
|
||||||
|
} else if (appAccount.getAnalyticDistributionTypeSelect()
|
||||||
|
== AppAccountRepository.DISTRIBUTION_TYPE_PRODUCT) {
|
||||||
|
return accountManagementServiceAccountImpl.getAnalyticDistributionTemplate(product, company);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnalyticMoveLine createAnalyticMoveLine(
|
||||||
|
AnalyticDistributionLine analyticDistributionLine,
|
||||||
|
BigDecimal total,
|
||||||
|
int typeSelect,
|
||||||
|
LocalDate date) {
|
||||||
|
|
||||||
|
AnalyticMoveLine analyticMoveLine = new AnalyticMoveLine();
|
||||||
|
analyticMoveLine.setOriginalPieceAmount(total);
|
||||||
|
analyticMoveLine.setAnalyticAccount(analyticDistributionLine.getAnalyticAccount());
|
||||||
|
analyticMoveLine.setAnalyticAxis(analyticDistributionLine.getAnalyticAxis());
|
||||||
|
analyticMoveLine.setAnalyticJournal(analyticDistributionLine.getAnalyticJournal());
|
||||||
|
|
||||||
|
AnalyticJournal analyticJournal = analyticDistributionLine.getAnalyticJournal();
|
||||||
|
Company company = analyticJournal == null ? null : analyticJournal.getCompany();
|
||||||
|
if (company != null) {
|
||||||
|
analyticMoveLine.setCurrency(company.getCurrency());
|
||||||
|
}
|
||||||
|
analyticMoveLine.setDate(date);
|
||||||
|
analyticMoveLine.setPercentage(analyticDistributionLine.getPercentage());
|
||||||
|
analyticMoveLine.setAmount(computeAmount(analyticMoveLine));
|
||||||
|
analyticMoveLine.setTypeSelect(typeSelect);
|
||||||
|
|
||||||
|
return analyticMoveLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateAnalyticMoveLine(
|
||||||
|
AnalyticMoveLine analyticMoveLine, BigDecimal total, LocalDate date) {
|
||||||
|
|
||||||
|
analyticMoveLine.setOriginalPieceAmount(total);
|
||||||
|
analyticMoveLine.setAmount(computeAmount(analyticMoveLine));
|
||||||
|
analyticMoveLine.setDate(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateLines(List<AnalyticDistributionLine> analyticDistributionLineList) {
|
||||||
|
if (analyticDistributionLineList != null) {
|
||||||
|
Map<AnalyticAxis, BigDecimal> map = new HashMap<AnalyticAxis, BigDecimal>();
|
||||||
|
for (AnalyticDistributionLine analyticDistributionLine : analyticDistributionLineList) {
|
||||||
|
if (map.containsKey(analyticDistributionLine.getAnalyticAxis())) {
|
||||||
|
map.put(
|
||||||
|
analyticDistributionLine.getAnalyticAxis(),
|
||||||
|
map.get(analyticDistributionLine.getAnalyticAxis())
|
||||||
|
.add(analyticDistributionLine.getPercentage()));
|
||||||
|
} else {
|
||||||
|
map.put(
|
||||||
|
analyticDistributionLine.getAnalyticAxis(), analyticDistributionLine.getPercentage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (AnalyticAxis analyticAxis : map.keySet()) {
|
||||||
|
if (map.get(analyticAxis).compareTo(new BigDecimal(100)) > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.AccountManagement;
|
||||||
|
import com.axelor.apps.account.db.AccountingSituation;
|
||||||
|
import com.axelor.apps.account.db.PaymentMode;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentModeRepository;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentModeService;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.repo.PartnerRepository;
|
||||||
|
import com.axelor.apps.base.service.BankDetailsServiceImpl;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.apps.tool.StringTool;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class BankDetailsServiceAccountImpl extends BankDetailsServiceImpl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In this implementation, we use the O2M in payment mode.
|
||||||
|
*
|
||||||
|
* @param company
|
||||||
|
* @param paymentMode
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String createCompanyBankDetailsDomain(
|
||||||
|
Partner partner, Company company, PaymentMode paymentMode, Integer operationTypeSelect)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
if (!Beans.get(AppBaseService.class).getAppBase().getManageMultiBanks()) {
|
||||||
|
return super.createCompanyBankDetailsDomain(
|
||||||
|
partner, company, paymentMode, operationTypeSelect);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (partner != null) {
|
||||||
|
partner = Beans.get(PartnerRepository.class).find(partner.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BankDetails> authorizedBankDetails = new ArrayList<>();
|
||||||
|
|
||||||
|
if (partner != null
|
||||||
|
&& partner.getFactorizedCustomer()
|
||||||
|
&& operationTypeSelect != null
|
||||||
|
&& (operationTypeSelect.intValue() == InvoiceRepository.OPERATION_TYPE_CLIENT_SALE
|
||||||
|
|| operationTypeSelect.intValue()
|
||||||
|
== InvoiceRepository.OPERATION_TYPE_CLIENT_REFUND)) {
|
||||||
|
|
||||||
|
authorizedBankDetails = createCompanyBankDetailsDomainFromFactorPartner(company);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (paymentMode == null) {
|
||||||
|
return "self.id IN (0)";
|
||||||
|
}
|
||||||
|
List<AccountManagement> accountManagementList = paymentMode.getAccountManagementList();
|
||||||
|
|
||||||
|
authorizedBankDetails = new ArrayList<>();
|
||||||
|
|
||||||
|
for (AccountManagement accountManagement : accountManagementList) {
|
||||||
|
if (accountManagement.getCompany() != null
|
||||||
|
&& accountManagement.getCompany().equals(company)) {
|
||||||
|
authorizedBankDetails.add(accountManagement.getBankDetails());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authorizedBankDetails.isEmpty()) {
|
||||||
|
return "self.id IN (0)";
|
||||||
|
} else {
|
||||||
|
return "self.id IN ("
|
||||||
|
+ StringTool.getIdListString(authorizedBankDetails)
|
||||||
|
+ ") AND self.active = true";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<BankDetails> createCompanyBankDetailsDomainFromFactorPartner(Company company)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
AccountConfig accountConfig = Beans.get(AccountConfigService.class).getAccountConfig(company);
|
||||||
|
List<BankDetails> bankDetailsList = accountConfig.getFactorPartner().getBankDetailsList();
|
||||||
|
return bankDetailsList
|
||||||
|
.stream()
|
||||||
|
.filter(bankDetails -> bankDetails.getActive())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a default bank details.
|
||||||
|
*
|
||||||
|
* @param company
|
||||||
|
* @param paymentMode
|
||||||
|
* @param partner
|
||||||
|
* @return the default bank details in accounting situation if it is active and allowed by the
|
||||||
|
* payment mode, or an authorized bank details if he is the only one authorized.
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public BankDetails getDefaultCompanyBankDetails(
|
||||||
|
Company company, PaymentMode paymentMode, Partner partner, Integer operationTypeSelect)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
if (!Beans.get(AppBaseService.class).getAppBase().getManageMultiBanks()) {
|
||||||
|
return super.getDefaultCompanyBankDetails(company, paymentMode, partner, operationTypeSelect);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (partner != null
|
||||||
|
&& partner.getFactorizedCustomer()
|
||||||
|
&& operationTypeSelect != null
|
||||||
|
&& (operationTypeSelect.intValue() == InvoiceRepository.OPERATION_TYPE_CLIENT_SALE
|
||||||
|
|| operationTypeSelect.intValue()
|
||||||
|
== InvoiceRepository.OPERATION_TYPE_CLIENT_REFUND)) {
|
||||||
|
|
||||||
|
return getDefaultCompanyBankDetailsFromFactorPartner(company);
|
||||||
|
} else {
|
||||||
|
if (paymentMode == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BankDetails candidateBankDetails =
|
||||||
|
getDefaultCompanyBankDetailsFromPartner(company, paymentMode, partner);
|
||||||
|
|
||||||
|
List<BankDetails> authorizedBankDetails =
|
||||||
|
Beans.get(PaymentModeService.class).getCompatibleBankDetailsList(paymentMode, company);
|
||||||
|
if (candidateBankDetails != null
|
||||||
|
&& authorizedBankDetails.contains(candidateBankDetails)
|
||||||
|
&& candidateBankDetails.getActive()) {
|
||||||
|
return candidateBankDetails;
|
||||||
|
}
|
||||||
|
// we did not find a bank details in accounting situation
|
||||||
|
else {
|
||||||
|
if (authorizedBankDetails.size() == 1) {
|
||||||
|
return authorizedBankDetails.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BankDetails getDefaultCompanyBankDetailsFromFactorPartner(Company company)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
AccountConfig accountConfig = Beans.get(AccountConfigService.class).getAccountConfig(company);
|
||||||
|
if (accountConfig.getFactorPartner() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<BankDetails> bankDetailsList = accountConfig.getFactorPartner().getBankDetailsList();
|
||||||
|
return bankDetailsList
|
||||||
|
.stream()
|
||||||
|
.filter(bankDetails -> bankDetails.getIsDefault())
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for the bank details in accounting situation.
|
||||||
|
*
|
||||||
|
* @param company
|
||||||
|
* @param paymentMode
|
||||||
|
* @param partner
|
||||||
|
* @return The bank details corresponding to the partner and the company with the right payment
|
||||||
|
* mode null if the partner is null or the accounting situation empty
|
||||||
|
*/
|
||||||
|
protected BankDetails getDefaultCompanyBankDetailsFromPartner(
|
||||||
|
Company company, PaymentMode paymentMode, Partner partner) {
|
||||||
|
|
||||||
|
if (partner == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
AccountingSituation accountingSituation =
|
||||||
|
Beans.get(AccountingSituationService.class).getAccountingSituation(partner, company);
|
||||||
|
if (accountingSituation == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
BankDetails candidateBankDetails = null;
|
||||||
|
if (paymentMode.getInOutSelect() == PaymentModeRepository.IN) {
|
||||||
|
candidateBankDetails = accountingSituation.getCompanyInBankDetails();
|
||||||
|
} else if (paymentMode.getInOutSelect() == PaymentModeRepository.OUT) {
|
||||||
|
candidateBankDetails = accountingSituation.getCompanyOutBankDetails();
|
||||||
|
}
|
||||||
|
return candidateBankDetails;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Budget;
|
||||||
|
import com.axelor.apps.account.db.BudgetDistribution;
|
||||||
|
import com.axelor.apps.account.db.BudgetLine;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.InvoiceLine;
|
||||||
|
import com.axelor.apps.account.db.repo.BudgetDistributionRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.BudgetLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.BudgetRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class BudgetService {
|
||||||
|
|
||||||
|
protected BudgetLineRepository budgetLineRepository;
|
||||||
|
protected BudgetRepository budgetRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public BudgetService(
|
||||||
|
BudgetLineRepository budgetLineRepository, BudgetRepository budgetRepository) {
|
||||||
|
this.budgetLineRepository = budgetLineRepository;
|
||||||
|
this.budgetRepository = budgetRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal compute(Budget budget) {
|
||||||
|
BigDecimal total = BigDecimal.ZERO;
|
||||||
|
if (budget.getBudgetLineList() != null) {
|
||||||
|
for (BudgetLine budgetLine : budget.getBudgetLineList()) {
|
||||||
|
total = total.add(budgetLine.getAmountExpected());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public BigDecimal computeTotalAmountRealized(Budget budget) {
|
||||||
|
List<BudgetLine> budgetLineList = budget.getBudgetLineList();
|
||||||
|
|
||||||
|
if (budgetLineList == null) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal totalAmountRealized =
|
||||||
|
budgetLineList
|
||||||
|
.stream()
|
||||||
|
.map(BudgetLine::getAmountRealized)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
|
budget.setTotalAmountRealized(totalAmountRealized);
|
||||||
|
|
||||||
|
return totalAmountRealized;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<BudgetLine> updateLines(Budget budget) {
|
||||||
|
if (budget.getBudgetLineList() != null && !budget.getBudgetLineList().isEmpty()) {
|
||||||
|
for (BudgetLine budgetLine : budget.getBudgetLineList()) {
|
||||||
|
budgetLine.setAmountRealized(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
List<BudgetDistribution> budgetDistributionList =
|
||||||
|
Beans.get(BudgetDistributionRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.budget.id = ?1 AND (self.invoiceLine.invoice.statusSelect = ?2 OR self.invoiceLine.invoice.statusSelect = ?3)",
|
||||||
|
budget.getId(),
|
||||||
|
InvoiceRepository.STATUS_VALIDATED,
|
||||||
|
InvoiceRepository.STATUS_VENTILATED)
|
||||||
|
.fetch();
|
||||||
|
for (BudgetDistribution budgetDistribution : budgetDistributionList) {
|
||||||
|
Optional<LocalDate> optionaldate = getDate(budgetDistribution);
|
||||||
|
optionaldate.ifPresent(
|
||||||
|
date -> {
|
||||||
|
for (BudgetLine budgetLine : budget.getBudgetLineList()) {
|
||||||
|
LocalDate fromDate = budgetLine.getFromDate();
|
||||||
|
LocalDate toDate = budgetLine.getToDate();
|
||||||
|
if ((fromDate.isBefore(date) || fromDate.isEqual(date))
|
||||||
|
&& (toDate.isAfter(date) || toDate.isEqual(date))) {
|
||||||
|
budgetLine.setAmountRealized(
|
||||||
|
budgetLine.getAmountRealized().add(budgetDistribution.getAmount()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return budget.getBudgetLineList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param budgetDistribution
|
||||||
|
* @return returns an {@code Optional} because in some cases the child implementations can return
|
||||||
|
* a null value.
|
||||||
|
*/
|
||||||
|
protected Optional<LocalDate> getDate(BudgetDistribution budgetDistribution) {
|
||||||
|
Invoice invoice = budgetDistribution.getInvoiceLine().getInvoice();
|
||||||
|
|
||||||
|
LocalDate invoiceDate = invoice.getInvoiceDate();
|
||||||
|
if (invoiceDate != null) {
|
||||||
|
return Optional.of(invoiceDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(invoice.getValidatedDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BudgetLine> generatePeriods(Budget budget) throws AxelorException {
|
||||||
|
|
||||||
|
if (budget.getBudgetLineList() != null && !budget.getBudgetLineList().isEmpty()) {
|
||||||
|
List<BudgetLine> budgetLineList = budget.getBudgetLineList();
|
||||||
|
budgetLineList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BudgetLine> budgetLineList = new ArrayList<BudgetLine>();
|
||||||
|
Integer duration = budget.getPeriodDurationSelect();
|
||||||
|
LocalDate fromDate = budget.getFromDate();
|
||||||
|
LocalDate toDate = budget.getToDate();
|
||||||
|
LocalDate budgetLineToDate = fromDate;
|
||||||
|
Integer budgetLineNumber = 1;
|
||||||
|
|
||||||
|
int c = 0;
|
||||||
|
int loopLimit = 1000;
|
||||||
|
while (budgetLineToDate.isBefore(toDate)) {
|
||||||
|
if (budgetLineNumber != 1) fromDate = fromDate.plusMonths(duration);
|
||||||
|
if (c >= loopLimit) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY, I18n.get(IExceptionMessage.BUDGET_1));
|
||||||
|
}
|
||||||
|
c += 1;
|
||||||
|
budgetLineToDate = fromDate.plusMonths(duration).minusDays(1);
|
||||||
|
if (budgetLineToDate.isAfter(toDate)) budgetLineToDate = toDate;
|
||||||
|
if (fromDate.isAfter(toDate)) continue;
|
||||||
|
BudgetLine budgetLine = new BudgetLine();
|
||||||
|
budgetLine.setFromDate(fromDate);
|
||||||
|
budgetLine.setToDate(budgetLineToDate);
|
||||||
|
budgetLine.setBudget(budget);
|
||||||
|
budgetLine.setAmountExpected(budget.getAmountForGeneration());
|
||||||
|
budgetLineList.add(budgetLine);
|
||||||
|
budgetLineNumber++;
|
||||||
|
}
|
||||||
|
return budgetLineList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkSharedDates(Budget budget) throws AxelorException {
|
||||||
|
|
||||||
|
if (budget.getBudgetLineList() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BudgetLine> budgetLineList = budget.getBudgetLineList();
|
||||||
|
|
||||||
|
for (int i = 0; i < budgetLineList.size() - 1; i++) {
|
||||||
|
BudgetLine budgetLineA = budgetLineList.get(i);
|
||||||
|
LocalDate fromDateA = budgetLineA.getFromDate();
|
||||||
|
LocalDate toDateA = budgetLineA.getToDate();
|
||||||
|
|
||||||
|
for (int j = i + 1; j < budgetLineList.size(); j++) {
|
||||||
|
BudgetLine budgetLineB = budgetLineList.get(j);
|
||||||
|
LocalDate fromDateB = budgetLineB.getFromDate();
|
||||||
|
LocalDate toDateB = budgetLineB.getToDate();
|
||||||
|
|
||||||
|
if (fromDateA.equals(fromDateB) || toDateA.equals(toDateB)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get("Two or more budget lines share dates"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromDateA.isBefore(fromDateB) && (!toDateA.isBefore(fromDateB))) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get("Two or more budget lines share dates"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromDateA.isAfter(fromDateB) && (!fromDateA.isAfter(toDateB))) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get("Two or more budget lines share dates"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void validate(Budget budget) {
|
||||||
|
budget.setStatusSelect(BudgetRepository.STATUS_VALIDATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void draft(Budget budget) {
|
||||||
|
budget.setStatusSelect(BudgetRepository.STATUS_DRAFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBudgetLinesFromInvoice(Invoice invoice) {
|
||||||
|
List<InvoiceLine> invoiceLineList = invoice.getInvoiceLineList();
|
||||||
|
|
||||||
|
if (invoiceLineList == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
invoiceLineList
|
||||||
|
.stream()
|
||||||
|
.filter(invoiceLine -> invoiceLine.getBudgetDistributionList() != null)
|
||||||
|
.flatMap(x -> x.getBudgetDistributionList().stream())
|
||||||
|
.forEach(
|
||||||
|
budgetDistribution -> {
|
||||||
|
Budget budget = budgetDistribution.getBudget();
|
||||||
|
updateLines(budget);
|
||||||
|
computeTotalAmountRealized(budget);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,150 @@
|
|||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.CashInventory;
|
||||||
|
import com.axelor.apps.account.db.CashInventoryLine;
|
||||||
|
import com.axelor.apps.account.db.CashRegister;
|
||||||
|
import com.axelor.apps.account.db.repo.CashDenominationRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.CashInventoryRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.CashRegisterRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.auth.AuthUtils;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CashInventoryService {
|
||||||
|
|
||||||
|
private SequenceService sequenceService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CashInventoryService(SequenceService sequenceService) {
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the theorical solde in words for a new cash inventory.
|
||||||
|
*
|
||||||
|
* @return the theorical solde in words as a BigDecimal
|
||||||
|
*/
|
||||||
|
public BigDecimal initThetoricalSolde() {
|
||||||
|
CashRegisterRepository casRegisterRepository = Beans.get(CashRegisterRepository.class);
|
||||||
|
CashRegister cashRegister = casRegisterRepository.all().order("-createdOn").fetchOne();
|
||||||
|
BigDecimal theoricalSolde = BigDecimal.ZERO;
|
||||||
|
if (cashRegister == null) {
|
||||||
|
theoricalSolde = BigDecimal.ZERO;
|
||||||
|
} else {
|
||||||
|
theoricalSolde = cashRegister.getTheoricalSolde();
|
||||||
|
}
|
||||||
|
return theoricalSolde;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the totals for the cash inventory, including total bank notes, total
|
||||||
|
* coins, physical
|
||||||
|
* solde, and gap.
|
||||||
|
*
|
||||||
|
* @param cashInventory The cash inventory to compute totals for.
|
||||||
|
* @return A map containing the computed totals.
|
||||||
|
*/
|
||||||
|
public Map<String, BigDecimal> computeToTals(CashInventory cashInventory) {
|
||||||
|
|
||||||
|
HashMap<String, BigDecimal> map = new HashMap<>();
|
||||||
|
|
||||||
|
List<CashInventoryLine> cashInventoryLines = cashInventory.getCashInventoryLines();
|
||||||
|
|
||||||
|
BigDecimal theoricalSolde = cashInventory.getTheoricalSolde();
|
||||||
|
|
||||||
|
BigDecimal totalBankNotes = BigDecimal.ZERO;
|
||||||
|
BigDecimal totalCoins = BigDecimal.ZERO;
|
||||||
|
BigDecimal physicalSolde = BigDecimal.ZERO;
|
||||||
|
BigDecimal gap = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
for (CashInventoryLine cashInventoryLine : cashInventoryLines) {
|
||||||
|
switch (cashInventoryLine.getCashDenomination().getTypeSelect()) {
|
||||||
|
case CashDenominationRepository.BANK_NOTE_TYPE:
|
||||||
|
totalBankNotes = totalBankNotes.add(cashInventoryLine.getTotalCashCount());
|
||||||
|
break;
|
||||||
|
case CashDenominationRepository.COINT_TYPE:
|
||||||
|
totalCoins = totalCoins.add(cashInventoryLine.getTotalCashCount());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
totalBankNotes = BigDecimal.ZERO;
|
||||||
|
totalCoins = BigDecimal.ZERO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
physicalSolde = physicalSolde.add(totalBankNotes).add(totalCoins);
|
||||||
|
gap = physicalSolde.subtract(theoricalSolde);
|
||||||
|
|
||||||
|
map.put("totalCoinsAmount", totalCoins);
|
||||||
|
map.put("totalBankNotesAmount", totalBankNotes);
|
||||||
|
map.put("totalCash", totalBankNotes);
|
||||||
|
map.put("physicalSolde", physicalSolde);
|
||||||
|
map.put("gap", gap);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCashInventorySequence(CashInventory cashInventory) throws AxelorException {
|
||||||
|
Integer operationTypeSelect = cashInventory.getOperationTypeSelect();
|
||||||
|
Company company = cashInventory.getCompany();
|
||||||
|
String sequence = null;
|
||||||
|
|
||||||
|
if (operationTypeSelect != null) {
|
||||||
|
switch (operationTypeSelect) {
|
||||||
|
case 1: // Cash inventory daily
|
||||||
|
sequence = "CASH_INVENTORY_DAILY";
|
||||||
|
break;
|
||||||
|
case 2: // Cash inventory monthly
|
||||||
|
sequence = "CASH_INVENTORY_MONTHLY";
|
||||||
|
break;
|
||||||
|
case 3: // Cash inventory annual
|
||||||
|
sequence = "CASH_INVENTORY_ANNUAL";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sequence = "CASH_INVENTORY";
|
||||||
|
// Default case for other operation types
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sequence = "CASH_INVENTORY";
|
||||||
|
}
|
||||||
|
|
||||||
|
String ref = sequenceService.getSequenceNumber(sequence, company);
|
||||||
|
if (ref == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.CASH_INVENTORY_MISSING_SEQUENCE),
|
||||||
|
company.getName());
|
||||||
|
} else {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void approveCashInventory(CashInventory cashInventory) {
|
||||||
|
CashRegisterRepository casRegisterRepository = Beans.get(CashRegisterRepository.class);
|
||||||
|
CashRegister cashRegister = casRegisterRepository.all().order("-createdOn").fetchOne();
|
||||||
|
// cashRegister.setTheoricalSolde(cashInventory.getPhysicalSolde());
|
||||||
|
cashRegister.setPhysicalSolde(cashInventory.getPhysicalSolde());
|
||||||
|
cashInventory.setValdiatedByUser(AuthUtils.getUser());
|
||||||
|
cashInventory.setValidattionDate(LocalDateTime.now());
|
||||||
|
cashInventory.setStatusSelect(3);
|
||||||
|
Beans.get(CashInventoryRepository.class).save(cashInventory);
|
||||||
|
casRegisterRepository.save(cashRegister);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.ChequeRejection;
|
||||||
|
import com.axelor.apps.account.db.InterbankCodeLine;
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.PaymentVoucher;
|
||||||
|
import com.axelor.apps.account.db.repo.ChequeRejectionRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveLineService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public class ChequeRejectionService {
|
||||||
|
|
||||||
|
protected MoveService moveService;
|
||||||
|
protected MoveLineService moveLineService;
|
||||||
|
protected SequenceService sequenceService;
|
||||||
|
protected AccountConfigService accountConfigService;
|
||||||
|
protected ChequeRejectionRepository chequeRejectionRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ChequeRejectionService(
|
||||||
|
MoveService moveService,
|
||||||
|
MoveLineService moveLineService,
|
||||||
|
SequenceService sequenceService,
|
||||||
|
AccountConfigService accountConfigService,
|
||||||
|
ChequeRejectionRepository chequeRejectionRepository) {
|
||||||
|
|
||||||
|
this.moveService = moveService;
|
||||||
|
this.moveLineService = moveLineService;
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
this.accountConfigService = accountConfigService;
|
||||||
|
this.chequeRejectionRepository = chequeRejectionRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* procédure de validation du rejet de chèque
|
||||||
|
*
|
||||||
|
* @param chequeRejection Un rejet de chèque brouillon
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void validateChequeRejection(ChequeRejection chequeRejection) throws AxelorException {
|
||||||
|
|
||||||
|
Company company = chequeRejection.getCompany();
|
||||||
|
|
||||||
|
this.testCompanyField(company);
|
||||||
|
|
||||||
|
this.setSequence(chequeRejection);
|
||||||
|
|
||||||
|
Move move = this.createChequeRejectionMove(chequeRejection, company);
|
||||||
|
|
||||||
|
chequeRejection.setMove(move);
|
||||||
|
|
||||||
|
chequeRejection.setStatusSelect(ChequeRejectionRepository.STATUS_VALIDATED);
|
||||||
|
|
||||||
|
chequeRejectionRepository.save(chequeRejection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de créer une écriture de rejet de chèque (L'extourne de l'écriture de
|
||||||
|
* paiement)
|
||||||
|
*
|
||||||
|
* @param chequeRejection Un rejet de cheque brouillon
|
||||||
|
* @param company Une société
|
||||||
|
* @return L'écriture de rejet de chèque
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public Move createChequeRejectionMove(ChequeRejection chequeRejection, Company company)
|
||||||
|
throws AxelorException {
|
||||||
|
this.testCompanyField(company);
|
||||||
|
|
||||||
|
Journal journal = company.getAccountConfig().getRejectJournal();
|
||||||
|
|
||||||
|
PaymentVoucher paymentVoucher = chequeRejection.getPaymentVoucher();
|
||||||
|
|
||||||
|
Move paymentMove = paymentVoucher.getGeneratedMove();
|
||||||
|
|
||||||
|
Partner partner = paymentVoucher.getPartner();
|
||||||
|
|
||||||
|
InterbankCodeLine interbankCodeLine = chequeRejection.getInterbankCodeLine();
|
||||||
|
|
||||||
|
String description = chequeRejection.getDescription();
|
||||||
|
|
||||||
|
LocalDate rejectionDate = chequeRejection.getRejectionDate();
|
||||||
|
|
||||||
|
// Move
|
||||||
|
Move move =
|
||||||
|
moveService
|
||||||
|
.getMoveCreateService()
|
||||||
|
.createMove(
|
||||||
|
journal,
|
||||||
|
company,
|
||||||
|
null,
|
||||||
|
partner,
|
||||||
|
rejectionDate,
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
|
||||||
|
int ref = 1;
|
||||||
|
|
||||||
|
for (MoveLine moveLine : paymentMove.getMoveLineList()) {
|
||||||
|
|
||||||
|
if (moveLine.getCredit().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
// Debit MoveLine
|
||||||
|
MoveLine debitMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
moveLine.getAccount(),
|
||||||
|
moveLine.getCredit(),
|
||||||
|
true,
|
||||||
|
rejectionDate,
|
||||||
|
ref,
|
||||||
|
chequeRejection.getName(),
|
||||||
|
chequeRejection.getDescription());
|
||||||
|
move.getMoveLineList().add(debitMoveLine);
|
||||||
|
debitMoveLine.setInterbankCodeLine(interbankCodeLine);
|
||||||
|
debitMoveLine.setDescription(description);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Credit MoveLine
|
||||||
|
MoveLine creditMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
moveLine.getAccount(),
|
||||||
|
moveLine.getDebit(),
|
||||||
|
false,
|
||||||
|
rejectionDate,
|
||||||
|
ref,
|
||||||
|
chequeRejection.getName(),
|
||||||
|
chequeRejection.getDescription());
|
||||||
|
move.getMoveLineList().add(creditMoveLine);
|
||||||
|
creditMoveLine.setInterbankCodeLine(interbankCodeLine);
|
||||||
|
creditMoveLine.setDescription(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
ref++;
|
||||||
|
}
|
||||||
|
|
||||||
|
move.setRejectOk(true);
|
||||||
|
|
||||||
|
moveService.getMoveValidateService().validate(move);
|
||||||
|
|
||||||
|
return move;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de vérifier les champs d'une société
|
||||||
|
*
|
||||||
|
* @param company Une société
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void testCompanyField(Company company) throws AxelorException {
|
||||||
|
|
||||||
|
accountConfigService.getRejectJournal(accountConfigService.getAccountConfig(company));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant d'assigner une séquence de rejet de chèque
|
||||||
|
*
|
||||||
|
* @param chequeRejection Un rejet de chèque
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void setSequence(ChequeRejection chequeRejection) throws AxelorException {
|
||||||
|
|
||||||
|
String seq =
|
||||||
|
sequenceService.getSequenceNumber(
|
||||||
|
SequenceRepository.CHEQUE_REJECT, chequeRejection.getCompany());
|
||||||
|
|
||||||
|
if (seq == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
chequeRejection,
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.CHECK_REJECTION_1),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
chequeRejection.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
chequeRejection.setName(seq);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.DepositSlip;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface DepositSlipService {
|
||||||
|
/**
|
||||||
|
* Load payments into deposit slip.
|
||||||
|
*
|
||||||
|
* @param depositSlip
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
void loadPayments(DepositSlip depositSlip) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish deposit slip.
|
||||||
|
*
|
||||||
|
* @param depositSlip
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
String publish(DepositSlip depositSlip) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get report filename.
|
||||||
|
*
|
||||||
|
* @param depositSlip
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
String getFilename(DepositSlip depositSlip) throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.ReportFactory;
|
||||||
|
import com.axelor.apps.account.db.DepositSlip;
|
||||||
|
import com.axelor.apps.account.db.PaymentVoucher;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentModeRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentVoucherRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.report.IReport;
|
||||||
|
import com.axelor.apps.account.service.payment.paymentvoucher.PaymentVoucherConfirmService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.apps.report.engine.ReportSettings;
|
||||||
|
import com.axelor.apps.tool.QueryBuilder;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DepositSlipServiceImpl implements DepositSlipService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void loadPayments(DepositSlip depositSlip) throws AxelorException {
|
||||||
|
if (depositSlip.getPublicationDate() != null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
depositSlip,
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.DEPOSIT_SLIP_ALREADY_PUBLISHED));
|
||||||
|
}
|
||||||
|
|
||||||
|
depositSlip.clearPaymentVoucherList();
|
||||||
|
|
||||||
|
fetchPaymentVouchers(depositSlip).forEach(depositSlip::addPaymentVoucherListItem);
|
||||||
|
compute(depositSlip);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public String publish(DepositSlip depositSlip) throws AxelorException {
|
||||||
|
confirmPayments(depositSlip);
|
||||||
|
|
||||||
|
ReportSettings settings =
|
||||||
|
ReportFactory.createReport(getReportName(depositSlip), getFilename(depositSlip));
|
||||||
|
settings.addParam("DepositSlipId", depositSlip.getId());
|
||||||
|
settings.addParam("Locale", ReportSettings.getPrintingLocale(null));
|
||||||
|
settings.addFormat("pdf");
|
||||||
|
String fileLink = settings.toAttach(depositSlip).generate().getFileLink();
|
||||||
|
depositSlip.setPublicationDate(Beans.get(AppBaseService.class).getTodayDate());
|
||||||
|
return fileLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFilename(DepositSlip depositSlip) throws AxelorException {
|
||||||
|
String name;
|
||||||
|
|
||||||
|
switch (depositSlip.getPaymentModeTypeSelect()) {
|
||||||
|
case PaymentModeRepository.TYPE_CHEQUE:
|
||||||
|
name = I18n.get("Cheque deposit slip");
|
||||||
|
break;
|
||||||
|
case PaymentModeRepository.TYPE_CASH:
|
||||||
|
name = I18n.get("Cash deposit slip");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AxelorException(
|
||||||
|
depositSlip,
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
IExceptionMessage.DEPOSIT_SLIP_UNSUPPORTED_PAYMENT_MODE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("%s - %s", name, depositSlip.getDepositNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getReportName(DepositSlip depositSlip) throws AxelorException {
|
||||||
|
switch (depositSlip.getPaymentModeTypeSelect()) {
|
||||||
|
case PaymentModeRepository.TYPE_CHEQUE:
|
||||||
|
return IReport.CHEQUE_DEPOSIT_SLIP;
|
||||||
|
case PaymentModeRepository.TYPE_CASH:
|
||||||
|
return IReport.CASH_DEPOSIT_SLIP;
|
||||||
|
default:
|
||||||
|
throw new AxelorException(
|
||||||
|
depositSlip,
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
IExceptionMessage.DEPOSIT_SLIP_UNSUPPORTED_PAYMENT_MODE_TYPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void compute(DepositSlip depositSlip) {
|
||||||
|
if (depositSlip.getPaymentVoucherList() != null) {
|
||||||
|
List<PaymentVoucher> paymentVoucherList = depositSlip.getPaymentVoucherList();
|
||||||
|
BigDecimal totalAmount =
|
||||||
|
paymentVoucherList
|
||||||
|
.stream()
|
||||||
|
.map(PaymentVoucher::getPaidAmount)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
depositSlip.setTotalAmount(totalAmount);
|
||||||
|
depositSlip.setChequeCount(paymentVoucherList.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PaymentVoucher> fetchPaymentVouchers(DepositSlip depositSlip) {
|
||||||
|
QueryBuilder<PaymentVoucher> queryBuilder = QueryBuilder.of(PaymentVoucher.class);
|
||||||
|
|
||||||
|
if (depositSlip.getPaymentModeTypeSelect() != 0) {
|
||||||
|
queryBuilder.add("self.paymentMode.typeSelect = :paymentModeTypeSelect");
|
||||||
|
queryBuilder.bind("paymentModeTypeSelect", depositSlip.getPaymentModeTypeSelect());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depositSlip.getCompany() != null) {
|
||||||
|
queryBuilder.add("self.company = :company");
|
||||||
|
queryBuilder.bind("company", depositSlip.getCompany());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depositSlip.getCurrency() != null) {
|
||||||
|
queryBuilder.add("self.currency = :currency");
|
||||||
|
queryBuilder.bind("currency", depositSlip.getCurrency());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depositSlip.getCompanyBankDetails() != null
|
||||||
|
&& Beans.get(AppBaseService.class).getAppBase().getManageMultiBanks()) {
|
||||||
|
queryBuilder.add("self.companyBankDetails = :companyBankDetails");
|
||||||
|
queryBuilder.bind("companyBankDetails", depositSlip.getCompanyBankDetails());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depositSlip.getFromDate() != null) {
|
||||||
|
if (depositSlip.getToDate() != null) {
|
||||||
|
queryBuilder.add(
|
||||||
|
"self.chequeDate IS NULL OR self.chequeDate BETWEEN :fromDate AND :toDate");
|
||||||
|
queryBuilder.bind("fromDate", depositSlip.getFromDate());
|
||||||
|
queryBuilder.bind("toDate", depositSlip.getToDate());
|
||||||
|
} else {
|
||||||
|
queryBuilder.add("self.chequeDate IS NULL OR self.chequeDate >= :fromDate");
|
||||||
|
queryBuilder.bind("fromDate", depositSlip.getFromDate());
|
||||||
|
}
|
||||||
|
} else if (depositSlip.getToDate() != null) {
|
||||||
|
queryBuilder.add("self.chequeDate IS NULL OR self.chequeDate <= :toDate");
|
||||||
|
queryBuilder.bind("toDate", depositSlip.getToDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
queryBuilder.add("self.depositSlip IS NULL");
|
||||||
|
|
||||||
|
queryBuilder.add("self.statusSelect = :statusSelect");
|
||||||
|
queryBuilder.bind("statusSelect", PaymentVoucherRepository.STATUS_WAITING_FOR_DEPOSIT_SLIP);
|
||||||
|
|
||||||
|
return queryBuilder.build().fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmPayments(DepositSlip depositSlip) throws AxelorException {
|
||||||
|
if (depositSlip.getPaymentVoucherList() != null) {
|
||||||
|
PaymentVoucherConfirmService paymentVoucherConfirmService =
|
||||||
|
Beans.get(PaymentVoucherConfirmService.class);
|
||||||
|
|
||||||
|
for (PaymentVoucher paymentVoucher : depositSlip.getPaymentVoucherList()) {
|
||||||
|
paymentVoucherConfirmService.createMoveAndConfirm(paymentVoucher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.FiscalPosition;
|
||||||
|
import com.axelor.apps.base.service.tax.FiscalPositionService;
|
||||||
|
|
||||||
|
public interface FiscalPositionAccountService extends FiscalPositionService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the account from the fiscal position account equiv list if match the given account
|
||||||
|
*
|
||||||
|
* @param fiscalPosition
|
||||||
|
* @param account
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Account getAccount(FiscalPosition fiscalPosition, Account account);
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountEquiv;
|
||||||
|
import com.axelor.apps.account.db.FiscalPosition;
|
||||||
|
import com.axelor.apps.base.service.tax.FiscalPositionServiceImpl;
|
||||||
|
|
||||||
|
public class FiscalPositionAccountServiceImpl extends FiscalPositionServiceImpl
|
||||||
|
implements FiscalPositionAccountService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account getAccount(FiscalPosition fiscalPosition, Account account) {
|
||||||
|
|
||||||
|
if (fiscalPosition != null && fiscalPosition.getAccountEquivList() != null) {
|
||||||
|
for (AccountEquiv accountEquiv : fiscalPosition.getAccountEquivList()) {
|
||||||
|
|
||||||
|
if (accountEquiv.getFromAccount().equals(account) && accountEquiv.getToAccount() != null) {
|
||||||
|
return accountEquiv.getToAccount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.FixedAssetLine;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
|
||||||
|
public interface FixedAssetLineService {
|
||||||
|
|
||||||
|
public void realize(FixedAssetLine fixedAssetLine) throws AxelorException;
|
||||||
|
|
||||||
|
public void generateDisposalMove(FixedAssetLine fixedAssetLine) throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.FixedAsset;
|
||||||
|
import com.axelor.apps.account.db.FixedAssetLine;
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.repo.FixedAssetLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.FixedAssetRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.service.move.MoveCreateService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class FixedAssetLineServiceImpl implements FixedAssetLineService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
@Inject private FixedAssetLineRepository fixedAssetLineRepo;
|
||||||
|
|
||||||
|
@Inject private MoveCreateService moveCreateService;
|
||||||
|
|
||||||
|
@Inject private MoveRepository moveRepo;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void realize(FixedAssetLine fixedAssetLine) throws AxelorException {
|
||||||
|
|
||||||
|
generateMove(fixedAssetLine);
|
||||||
|
|
||||||
|
fixedAssetLine.setStatusSelect(FixedAssetLineRepository.STATUS_REALIZED);
|
||||||
|
|
||||||
|
FixedAsset fixedAsset = fixedAssetLine.getFixedAsset();
|
||||||
|
BigDecimal residualValue = fixedAsset.getResidualValue();
|
||||||
|
fixedAsset.setResidualValue(residualValue.subtract(fixedAssetLine.getDepreciation()));
|
||||||
|
|
||||||
|
FixedAssetLine plannedFixedAssetLine =
|
||||||
|
fixedAsset
|
||||||
|
.getFixedAssetLineList()
|
||||||
|
.stream()
|
||||||
|
.filter(line -> line.getStatusSelect() == FixedAssetLineRepository.STATUS_PLANNED)
|
||||||
|
.findAny()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (plannedFixedAssetLine == null
|
||||||
|
&& fixedAsset.getDisposalValue().compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
fixedAsset.setStatusSelect(FixedAssetRepository.STATUS_DEPRECIATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
fixedAssetLineRepo.save(fixedAssetLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
private void generateMove(FixedAssetLine fixedAssetLine) throws AxelorException {
|
||||||
|
FixedAsset fixedAsset = fixedAssetLine.getFixedAsset();
|
||||||
|
|
||||||
|
Journal journal = fixedAsset.getJournal();
|
||||||
|
Company company = fixedAsset.getCompany();
|
||||||
|
Partner partner = fixedAsset.getPartner();
|
||||||
|
LocalDate date = fixedAsset.getAcquisitionDate();
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Creating an fixed asset line specific accounting entry {} (Company : {}, Journal : {})",
|
||||||
|
new Object[] {fixedAsset.getReference(), company.getName(), journal.getCode()});
|
||||||
|
|
||||||
|
// Creating move
|
||||||
|
Move move =
|
||||||
|
moveCreateService.createMove(
|
||||||
|
journal,
|
||||||
|
company,
|
||||||
|
company.getCurrency(),
|
||||||
|
partner,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
|
||||||
|
if (move != null) {
|
||||||
|
List<MoveLine> moveLines = new ArrayList<MoveLine>();
|
||||||
|
|
||||||
|
String origin = fixedAsset.getReference();
|
||||||
|
Account debitLineAccount = fixedAsset.getFixedAssetCategory().getChargeAccount();
|
||||||
|
Account creditLineAccount = fixedAsset.getFixedAssetCategory().getDepreciationAccount();
|
||||||
|
BigDecimal amount = fixedAssetLine.getDepreciation();
|
||||||
|
|
||||||
|
// Creating accounting debit move line
|
||||||
|
MoveLine debitMoveLine =
|
||||||
|
new MoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
debitLineAccount,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
amount,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
fixedAsset.getName(),
|
||||||
|
origin,
|
||||||
|
null,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
date);
|
||||||
|
moveLines.add(debitMoveLine);
|
||||||
|
|
||||||
|
// Creating accounting debit move line
|
||||||
|
MoveLine creditMoveLine =
|
||||||
|
new MoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
creditLineAccount,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
amount,
|
||||||
|
fixedAsset.getName(),
|
||||||
|
origin,
|
||||||
|
null,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
date);
|
||||||
|
moveLines.add(creditMoveLine);
|
||||||
|
|
||||||
|
move.getMoveLineList().addAll(moveLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveRepo.save(move);
|
||||||
|
|
||||||
|
fixedAssetLine.setDepreciationAccountMove(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void generateDisposalMove(FixedAssetLine fixedAssetLine) throws AxelorException {
|
||||||
|
|
||||||
|
FixedAsset fixedAsset = fixedAssetLine.getFixedAsset();
|
||||||
|
Journal journal = fixedAsset.getJournal();
|
||||||
|
Company company = fixedAsset.getCompany();
|
||||||
|
Partner partner = fixedAsset.getPartner();
|
||||||
|
LocalDate date = fixedAsset.getAcquisitionDate();
|
||||||
|
|
||||||
|
// Creating move
|
||||||
|
Move move =
|
||||||
|
moveCreateService.createMove(
|
||||||
|
journal,
|
||||||
|
company,
|
||||||
|
company.getCurrency(),
|
||||||
|
partner,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
|
||||||
|
if (move != null) {
|
||||||
|
List<MoveLine> moveLines = new ArrayList<MoveLine>();
|
||||||
|
|
||||||
|
String origin = fixedAsset.getReference();
|
||||||
|
Account chargeAccount = fixedAsset.getFixedAssetCategory().getChargeAccount();
|
||||||
|
Account depreciationAccount = fixedAsset.getFixedAssetCategory().getDepreciationAccount();
|
||||||
|
Account purchaseAccount = fixedAsset.getPurchaseAccount();
|
||||||
|
BigDecimal chargeAmount = fixedAssetLine.getResidualValue();
|
||||||
|
BigDecimal cumulativeDepreciationAmount = fixedAssetLine.getCumulativeDepreciation();
|
||||||
|
|
||||||
|
// Creating accounting debit move line for charge account
|
||||||
|
MoveLine chargeAccountDebitMoveLine =
|
||||||
|
new MoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
chargeAccount,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
chargeAmount,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
fixedAsset.getName(),
|
||||||
|
origin,
|
||||||
|
null,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
date);
|
||||||
|
moveLines.add(chargeAccountDebitMoveLine);
|
||||||
|
|
||||||
|
// Creating accounting debit move line for deprecation account
|
||||||
|
MoveLine deprecationAccountDebitMoveLine =
|
||||||
|
new MoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
depreciationAccount,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
cumulativeDepreciationAmount,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
fixedAsset.getName(),
|
||||||
|
origin,
|
||||||
|
null,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
date);
|
||||||
|
moveLines.add(deprecationAccountDebitMoveLine);
|
||||||
|
|
||||||
|
// Creating accounting credit move line
|
||||||
|
MoveLine creditMoveLine =
|
||||||
|
new MoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
purchaseAccount,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
fixedAsset.getGrossValue(),
|
||||||
|
fixedAsset.getName(),
|
||||||
|
origin,
|
||||||
|
null,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
date);
|
||||||
|
moveLines.add(creditMoveLine);
|
||||||
|
|
||||||
|
move.getMoveLineList().addAll(moveLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
moveRepo.save(move);
|
||||||
|
|
||||||
|
fixedAsset.setDisposalMove(move);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.FixedAsset;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface FixedAssetService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow to generate and compute the fixed asset lines
|
||||||
|
*
|
||||||
|
* @param fixedAsset
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public FixedAsset generateAndcomputeLines(FixedAsset fixedAsset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow to create fixed asset from invoice
|
||||||
|
*
|
||||||
|
* @param invoice
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public List<FixedAsset> createFixedAssets(Invoice invoice) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow to disposal remaining depreciation
|
||||||
|
*
|
||||||
|
* @param disposalDate
|
||||||
|
* @param disposalAmount
|
||||||
|
* @param fixedAsset
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void disposal(LocalDate disposalDate, BigDecimal disposalAmount, FixedAsset fixedAsset)
|
||||||
|
throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,329 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.FixedAsset;
|
||||||
|
import com.axelor.apps.account.db.FixedAssetLine;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.InvoiceLine;
|
||||||
|
import com.axelor.apps.account.db.repo.FixedAssetLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.FixedAssetRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
|
public class FixedAssetServiceImpl implements FixedAssetService {
|
||||||
|
|
||||||
|
@Inject FixedAssetRepository fixedAssetRepo;
|
||||||
|
|
||||||
|
@Inject FixedAssetLineService fixedAssetLineService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FixedAsset generateAndcomputeLines(FixedAsset fixedAsset) {
|
||||||
|
|
||||||
|
BigDecimal depreciationValue = this.computeDepreciationValue(fixedAsset);
|
||||||
|
BigDecimal cumulativeValue = depreciationValue;
|
||||||
|
LocalDate depreciationDate = fixedAsset.getFirstDepreciationDate();
|
||||||
|
LocalDate acquisitionDate = fixedAsset.getAcquisitionDate();
|
||||||
|
int numberOfDepreciation = fixedAsset.getNumberOfDepreciation();
|
||||||
|
boolean isProrataTemporis = fixedAsset.getFixedAssetCategory().getIsProrataTemporis();
|
||||||
|
LocalDate endDate = depreciationDate.plusMonths(fixedAsset.getDurationInMonth());
|
||||||
|
int counter = 1;
|
||||||
|
int scale = Beans.get(AppBaseService.class).getNbDecimalDigitForUnitPrice();
|
||||||
|
numberOfDepreciation--;
|
||||||
|
|
||||||
|
while (depreciationDate.isBefore(endDate)) {
|
||||||
|
FixedAssetLine fixedAssetLine = new FixedAssetLine();
|
||||||
|
fixedAssetLine.setStatusSelect(FixedAssetLineRepository.STATUS_PLANNED);
|
||||||
|
fixedAssetLine.setDepreciationDate(depreciationDate);
|
||||||
|
fixedAssetLine.setDepreciation(depreciationValue);
|
||||||
|
fixedAssetLine.setCumulativeDepreciation(cumulativeValue);
|
||||||
|
fixedAssetLine.setResidualValue(
|
||||||
|
fixedAsset.getGrossValue().subtract(fixedAssetLine.getCumulativeDepreciation()));
|
||||||
|
|
||||||
|
fixedAsset.addFixedAssetLineListItem(fixedAssetLine);
|
||||||
|
if (counter == numberOfDepreciation) {
|
||||||
|
depreciationValue = fixedAssetLine.getResidualValue();
|
||||||
|
cumulativeValue = cumulativeValue.add(depreciationValue);
|
||||||
|
depreciationDate = depreciationDate.plusMonths(fixedAsset.getPeriodicityInMonth());
|
||||||
|
if (isProrataTemporis) {
|
||||||
|
endDate =
|
||||||
|
depreciationDate.minusDays(
|
||||||
|
ChronoUnit.DAYS.between(acquisitionDate, fixedAsset.getFirstDepreciationDate()));
|
||||||
|
depreciationDate = endDate.minusDays(1);
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixedAsset.getComputationMethodSelect().equals("degressive")) {
|
||||||
|
if (counter > 2 && fixedAsset.getNumberOfDepreciation() > 3) {
|
||||||
|
if (counter == 3) {
|
||||||
|
int remainingYear = fixedAsset.getNumberOfDepreciation() - 3;
|
||||||
|
depreciationValue =
|
||||||
|
fixedAssetLine
|
||||||
|
.getResidualValue()
|
||||||
|
.divide(new BigDecimal(remainingYear), RoundingMode.HALF_EVEN);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
depreciationValue =
|
||||||
|
this.computeDepreciation(fixedAsset, fixedAssetLine.getResidualValue(), false);
|
||||||
|
}
|
||||||
|
depreciationDate = depreciationDate.plusMonths(fixedAsset.getPeriodicityInMonth());
|
||||||
|
} else {
|
||||||
|
depreciationValue =
|
||||||
|
this.computeDepreciation(fixedAsset, fixedAsset.getResidualValue(), false);
|
||||||
|
depreciationDate = depreciationDate.plusMonths(fixedAsset.getPeriodicityInMonth());
|
||||||
|
}
|
||||||
|
depreciationValue = depreciationValue.setScale(scale, RoundingMode.HALF_EVEN);
|
||||||
|
cumulativeValue =
|
||||||
|
cumulativeValue.add(depreciationValue).setScale(scale, RoundingMode.HALF_EVEN);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
return fixedAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal computeDepreciationValue(FixedAsset fixedAsset) {
|
||||||
|
BigDecimal depreciationValue = BigDecimal.ZERO;
|
||||||
|
depreciationValue = this.computeDepreciation(fixedAsset, fixedAsset.getGrossValue(), true);
|
||||||
|
return depreciationValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal computeProrataTemporis(FixedAsset fixedAsset, boolean isFirstYear) {
|
||||||
|
float prorataTemporis = 1;
|
||||||
|
if (isFirstYear && fixedAsset.getFixedAssetCategory().getIsProrataTemporis()) {
|
||||||
|
|
||||||
|
LocalDate acquisitionDate = fixedAsset.getAcquisitionDate();
|
||||||
|
LocalDate depreciationDate = fixedAsset.getFirstDepreciationDate();
|
||||||
|
|
||||||
|
long monthsBetweenDates =
|
||||||
|
ChronoUnit.MONTHS.between(
|
||||||
|
acquisitionDate.withDayOfMonth(1), depreciationDate.withDayOfMonth(1));
|
||||||
|
prorataTemporis = monthsBetweenDates / fixedAsset.getPeriodicityInMonth().floatValue();
|
||||||
|
}
|
||||||
|
return new BigDecimal(prorataTemporis);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal computeDepreciation(
|
||||||
|
FixedAsset fixedAsset, BigDecimal residualValue, boolean isFirstYear) {
|
||||||
|
|
||||||
|
int scale = Beans.get(AppBaseService.class).getNbDecimalDigitForUnitPrice();
|
||||||
|
int numberOfDepreciation =
|
||||||
|
fixedAsset.getFixedAssetCategory().getIsProrataTemporis()
|
||||||
|
? fixedAsset.getNumberOfDepreciation() - 1
|
||||||
|
: fixedAsset.getNumberOfDepreciation();
|
||||||
|
float depreciationRate = 1f / numberOfDepreciation * 100f;
|
||||||
|
BigDecimal ddRate = BigDecimal.ONE;
|
||||||
|
BigDecimal prorataTemporis = this.computeProrataTemporis(fixedAsset, isFirstYear);
|
||||||
|
if (fixedAsset.getComputationMethodSelect().equals("degressive")) {
|
||||||
|
ddRate = fixedAsset.getDegressiveCoef();
|
||||||
|
}
|
||||||
|
return residualValue
|
||||||
|
.multiply(new BigDecimal(depreciationRate))
|
||||||
|
.multiply(ddRate)
|
||||||
|
.multiply(prorataTemporis)
|
||||||
|
.divide(new BigDecimal(100), scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public List<FixedAsset> createFixedAssets(Invoice invoice) throws AxelorException {
|
||||||
|
|
||||||
|
if (invoice == null || CollectionUtils.isEmpty(invoice.getInvoiceLineList())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountConfig accountConfig =
|
||||||
|
Beans.get(AccountConfigService.class).getAccountConfig(invoice.getCompany());
|
||||||
|
List<FixedAsset> fixedAssetList = new ArrayList<FixedAsset>();
|
||||||
|
|
||||||
|
for (InvoiceLine invoiceLine : invoice.getInvoiceLineList()) {
|
||||||
|
|
||||||
|
if (accountConfig.getFixedAssetCatReqOnInvoice()
|
||||||
|
&& invoiceLine.getFixedAssets()
|
||||||
|
&& invoiceLine.getFixedAssetCategory() == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
invoiceLine,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.INVOICE_LINE_ERROR_FIXED_ASSET_CATEGORY),
|
||||||
|
invoiceLine.getProductName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!invoiceLine.getFixedAssets() || invoiceLine.getFixedAssetCategory() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedAsset fixedAsset = new FixedAsset();
|
||||||
|
fixedAsset.setFixedAssetCategory(invoiceLine.getFixedAssetCategory());
|
||||||
|
if (fixedAsset.getFixedAssetCategory().getIsValidateFixedAsset()) {
|
||||||
|
fixedAsset.setStatusSelect(FixedAssetRepository.STATUS_VALIDATED);
|
||||||
|
} else {
|
||||||
|
fixedAsset.setStatusSelect(FixedAssetRepository.STATUS_DRAFT);
|
||||||
|
}
|
||||||
|
fixedAsset.setAcquisitionDate(invoice.getInvoiceDate());
|
||||||
|
fixedAsset.setFirstDepreciationDate(invoice.getInvoiceDate());
|
||||||
|
fixedAsset.setReference(invoice.getInvoiceId());
|
||||||
|
fixedAsset.setName(invoiceLine.getProductName() + " (" + invoiceLine.getQty() + ")");
|
||||||
|
fixedAsset.setCompany(fixedAsset.getFixedAssetCategory().getCompany());
|
||||||
|
fixedAsset.setJournal(fixedAsset.getFixedAssetCategory().getJournal());
|
||||||
|
fixedAsset.setComputationMethodSelect(
|
||||||
|
fixedAsset.getFixedAssetCategory().getComputationMethodSelect());
|
||||||
|
fixedAsset.setDegressiveCoef(fixedAsset.getFixedAssetCategory().getDegressiveCoef());
|
||||||
|
fixedAsset.setNumberOfDepreciation(
|
||||||
|
fixedAsset.getFixedAssetCategory().getNumberOfDepreciation());
|
||||||
|
fixedAsset.setPeriodicityInMonth(fixedAsset.getFixedAssetCategory().getPeriodicityInMonth());
|
||||||
|
fixedAsset.setDurationInMonth(fixedAsset.getFixedAssetCategory().getDurationInMonth());
|
||||||
|
fixedAsset.setGrossValue(invoiceLine.getCompanyExTaxTotal());
|
||||||
|
fixedAsset.setPartner(invoice.getPartner());
|
||||||
|
fixedAsset.setPurchaseAccount(invoiceLine.getAccount());
|
||||||
|
fixedAsset.setInvoiceLine(invoiceLine);
|
||||||
|
|
||||||
|
this.generateAndcomputeLines(fixedAsset);
|
||||||
|
|
||||||
|
fixedAssetList.add(fixedAssetRepo.save(fixedAsset));
|
||||||
|
}
|
||||||
|
return fixedAssetList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void disposal(LocalDate disposalDate, BigDecimal disposalAmount, FixedAsset fixedAsset)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Map<Integer, List<FixedAssetLine>> FixedAssetLineMap =
|
||||||
|
fixedAsset
|
||||||
|
.getFixedAssetLineList()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.groupingBy(fa -> fa.getStatusSelect()));
|
||||||
|
List<FixedAssetLine> previousPlannedLineList =
|
||||||
|
FixedAssetLineMap.get(FixedAssetLineRepository.STATUS_PLANNED);
|
||||||
|
List<FixedAssetLine> previousRealizedLineList =
|
||||||
|
FixedAssetLineMap.get(FixedAssetLineRepository.STATUS_REALIZED);
|
||||||
|
FixedAssetLine previousPlannedLine =
|
||||||
|
previousPlannedLineList != null && !previousPlannedLineList.isEmpty()
|
||||||
|
? previousPlannedLineList.get(0)
|
||||||
|
: null;
|
||||||
|
FixedAssetLine previousRealizedLine =
|
||||||
|
previousRealizedLineList != null && !previousRealizedLineList.isEmpty()
|
||||||
|
? previousRealizedLineList.get(previousRealizedLineList.size() - 1)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (previousPlannedLine != null
|
||||||
|
&& disposalDate.isAfter(previousPlannedLine.getDepreciationDate())) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.FIXED_ASSET_DISPOSAL_DATE_ERROR_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousRealizedLine != null
|
||||||
|
&& disposalDate.isBefore(previousRealizedLine.getDepreciationDate())) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.FIXED_ASSET_DISPOSAL_DATE_ERROR_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disposalAmount.compareTo(BigDecimal.ZERO) != 0) {
|
||||||
|
|
||||||
|
FixedAssetLine depreciationFixedAssetLine =
|
||||||
|
generateProrataDepreciationLine(fixedAsset, disposalDate, previousRealizedLine);
|
||||||
|
fixedAssetLineService.realize(depreciationFixedAssetLine);
|
||||||
|
fixedAssetLineService.generateDisposalMove(depreciationFixedAssetLine);
|
||||||
|
} else {
|
||||||
|
if (disposalAmount.compareTo(fixedAsset.getResidualValue()) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<FixedAssetLine> fixedAssetLineList =
|
||||||
|
fixedAsset
|
||||||
|
.getFixedAssetLineList()
|
||||||
|
.stream()
|
||||||
|
.filter(
|
||||||
|
fixedAssetLine ->
|
||||||
|
fixedAssetLine.getStatusSelect() == FixedAssetLineRepository.STATUS_PLANNED)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
for (FixedAssetLine fixedAssetLine : fixedAssetLineList) {
|
||||||
|
fixedAsset.removeFixedAssetLineListItem(fixedAssetLine);
|
||||||
|
}
|
||||||
|
fixedAsset.setStatusSelect(FixedAssetRepository.STATUS_TRANSFERRED);
|
||||||
|
fixedAsset.setDisposalDate(disposalDate);
|
||||||
|
fixedAsset.setDisposalValue(disposalAmount);
|
||||||
|
fixedAssetRepo.save(fixedAsset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FixedAssetLine generateProrataDepreciationLine(
|
||||||
|
FixedAsset fixedAsset, LocalDate disposalDate, FixedAssetLine previousRealizedLine) {
|
||||||
|
|
||||||
|
LocalDate previousRealizedDate =
|
||||||
|
previousRealizedLine != null
|
||||||
|
? previousRealizedLine.getDepreciationDate()
|
||||||
|
: fixedAsset.getFirstDepreciationDate();
|
||||||
|
long monthsBetweenDates =
|
||||||
|
ChronoUnit.MONTHS.between(
|
||||||
|
previousRealizedDate.withDayOfMonth(1), disposalDate.withDayOfMonth(1));
|
||||||
|
|
||||||
|
FixedAssetLine fixedAssetLine = new FixedAssetLine();
|
||||||
|
fixedAssetLine.setDepreciationDate(disposalDate);
|
||||||
|
BigDecimal prorataTemporis =
|
||||||
|
new BigDecimal(monthsBetweenDates / fixedAsset.getPeriodicityInMonth().floatValue());
|
||||||
|
|
||||||
|
int scale = Beans.get(AppBaseService.class).getNbDecimalDigitForUnitPrice();
|
||||||
|
int numberOfDepreciation =
|
||||||
|
fixedAsset.getFixedAssetCategory().getIsProrataTemporis()
|
||||||
|
? fixedAsset.getNumberOfDepreciation() - 1
|
||||||
|
: fixedAsset.getNumberOfDepreciation();
|
||||||
|
float depreciationRate = 1f / numberOfDepreciation * 100f;
|
||||||
|
BigDecimal ddRate = BigDecimal.ONE;
|
||||||
|
if (fixedAsset.getComputationMethodSelect().equals("degressive")) {
|
||||||
|
ddRate = fixedAsset.getDegressiveCoef();
|
||||||
|
}
|
||||||
|
BigDecimal deprecationValue =
|
||||||
|
fixedAsset
|
||||||
|
.getGrossValue()
|
||||||
|
.multiply(new BigDecimal(depreciationRate))
|
||||||
|
.multiply(ddRate)
|
||||||
|
.multiply(prorataTemporis)
|
||||||
|
.divide(new BigDecimal(100), scale);
|
||||||
|
|
||||||
|
fixedAssetLine.setDepreciation(deprecationValue);
|
||||||
|
BigDecimal cumulativeValue =
|
||||||
|
previousRealizedLine != null
|
||||||
|
? previousRealizedLine.getCumulativeDepreciation().add(deprecationValue)
|
||||||
|
: deprecationValue;
|
||||||
|
fixedAssetLine.setCumulativeDepreciation(cumulativeValue);
|
||||||
|
fixedAssetLine.setResidualValue(
|
||||||
|
fixedAsset.getGrossValue().subtract(fixedAssetLine.getCumulativeDepreciation()));
|
||||||
|
fixedAsset.addFixedAssetLineListItem(fixedAssetLine);
|
||||||
|
return fixedAssetLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.InvoiceLine;
|
||||||
|
import com.axelor.apps.account.db.InvoiceTemplate;
|
||||||
|
import com.axelor.apps.account.db.InvoiceTemplateLine;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceRepository;
|
||||||
|
import com.axelor.apps.account.service.invoice.generator.InvoiceGenerator;
|
||||||
|
import com.axelor.apps.account.service.invoice.generator.InvoiceLineGenerator;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.Product;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class InvoiceTemplateService {
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Invoice generateInvoiceFromTemplate(InvoiceTemplate invoiceTemplate)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Partner partner = invoiceTemplate.getPartner();
|
||||||
|
Company company = invoiceTemplate.getCompany();
|
||||||
|
InvoiceGenerator invoiceGenerator =
|
||||||
|
new InvoiceGenerator(
|
||||||
|
InvoiceRepository.OPERATION_TYPE_SUPPLIER_PURCHASE,
|
||||||
|
company,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
partner,
|
||||||
|
partner,
|
||||||
|
partner.getCurrency(),
|
||||||
|
null,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
company.getDefaultBankDetails(),
|
||||||
|
null) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Invoice generate() throws AxelorException {
|
||||||
|
|
||||||
|
return super.createInvoiceHeader();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
List<InvoiceLine> invoiceLineList = new ArrayList<>();
|
||||||
|
|
||||||
|
Invoice invoice = invoiceGenerator.generate();
|
||||||
|
|
||||||
|
int priority = 0;
|
||||||
|
for (InvoiceTemplateLine invoiceTemplateLine : invoiceTemplate.getMoveTemplateLineList()) {
|
||||||
|
invoiceLineList.addAll(createInvoiceLine(invoice, invoiceTemplateLine, priority));
|
||||||
|
priority++;
|
||||||
|
}
|
||||||
|
invoiceGenerator.populate(invoice, invoiceLineList);
|
||||||
|
|
||||||
|
Invoice returnInvoiced = Beans.get(InvoiceRepository.class).save(invoice);
|
||||||
|
|
||||||
|
return returnInvoiced;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<InvoiceLine> createInvoiceLine(
|
||||||
|
Invoice invoice, InvoiceTemplateLine invoiceTemplateLine, int priority)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Product product = invoiceTemplateLine.getProduct();
|
||||||
|
|
||||||
|
InvoiceLineGenerator invoiceLineGenerator =
|
||||||
|
new InvoiceLineGenerator(
|
||||||
|
invoice,
|
||||||
|
product,
|
||||||
|
invoiceTemplateLine.getProduct().getName(),
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
"",
|
||||||
|
invoiceTemplateLine.getQty(),
|
||||||
|
invoiceTemplateLine.getProduct().getUnit(),
|
||||||
|
null,
|
||||||
|
priority,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
0,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
BigDecimal.ZERO,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<InvoiceLine> creates() throws AxelorException {
|
||||||
|
|
||||||
|
InvoiceLine invoiceLine = this.createInvoiceLine();
|
||||||
|
invoiceLine.setQty(BigDecimal.ONE);
|
||||||
|
invoiceLine.setPrice(BigDecimal.ZERO);
|
||||||
|
invoiceLine.setPriceDiscounted(BigDecimal.ZERO);
|
||||||
|
|
||||||
|
List<InvoiceLine> invoiceLines = new ArrayList<InvoiceLine>();
|
||||||
|
invoiceLines.add(invoiceLine);
|
||||||
|
|
||||||
|
return invoiceLines;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return invoiceLineGenerator.creates();
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class JournalService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
/** Debit balance = debit - credit */
|
||||||
|
public static final Integer BALANCE_TYPE_DEBIT_BALANCE = 1;
|
||||||
|
|
||||||
|
/** Credit balance = credit - debit */
|
||||||
|
public static final Integer BALANCE_TYPE_CREDIT_BALANCE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the balance of the journal, depending of the account type and balance type
|
||||||
|
*
|
||||||
|
* @param journal Journal
|
||||||
|
* @param accountType Technical type select of AccountType
|
||||||
|
* @param balanceType
|
||||||
|
* <p>1 : debit balance = debit - credit
|
||||||
|
* <p>2 : credit balance = credit - debit
|
||||||
|
* @return The balance (debit balance or credit balance)
|
||||||
|
*/
|
||||||
|
public BigDecimal computeBalance(Journal journal, int accountType, int balanceType) {
|
||||||
|
|
||||||
|
Query balanceQuery =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"select sum(self.debit - self.credit) from MoveLine self where self.move.journal = :journal "
|
||||||
|
+ "and self.move.ignoreInAccountingOk IN ('false', null) and self.move.statusSelect IN (2, 3) and self.account.accountType.technicalTypeSelect = :accountType");
|
||||||
|
|
||||||
|
balanceQuery.setParameter("journal", journal);
|
||||||
|
balanceQuery.setParameter("accountType", accountType);
|
||||||
|
|
||||||
|
BigDecimal balance = (BigDecimal) balanceQuery.getSingleResult();
|
||||||
|
|
||||||
|
if (balance != null) {
|
||||||
|
if (balanceType == BALANCE_TYPE_CREDIT_BALANCE) {
|
||||||
|
balance = balance.negate();
|
||||||
|
}
|
||||||
|
log.debug("Account balance : {}", balance);
|
||||||
|
|
||||||
|
return balance;
|
||||||
|
} else {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountingReport;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.meta.db.MetaFile;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public interface MoveLineExportService {
|
||||||
|
|
||||||
|
public MetaFile exportMoveLine(AccountingReport accountingReport)
|
||||||
|
throws AxelorException, IOException;
|
||||||
|
|
||||||
|
public void replayExportMoveLine(AccountingReport accountingReport)
|
||||||
|
throws AxelorException, IOException;
|
||||||
|
|
||||||
|
public AccountingReport createAccountingReport(
|
||||||
|
Company company, int exportTypeSelect, LocalDate startDate, LocalDate endDate)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
public void exportMoveLineTypeSelect1006(AccountingReport mlr, boolean replay)
|
||||||
|
throws AxelorException, IOException;
|
||||||
|
|
||||||
|
public void exportMoveLineTypeSelect1007(AccountingReport accountingReport, boolean replay)
|
||||||
|
throws AxelorException, IOException;
|
||||||
|
|
||||||
|
public void exportMoveLineTypeSelect1008(AccountingReport accountingReport, boolean replay)
|
||||||
|
throws AxelorException, IOException;
|
||||||
|
|
||||||
|
public void exportMoveLineTypeSelect1009(AccountingReport accountingReport, boolean replay)
|
||||||
|
throws AxelorException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export general balance to CSV file.
|
||||||
|
*
|
||||||
|
* @param accountingReport
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
void exportMoveLineTypeSelect1010(AccountingReport accountingReport)
|
||||||
|
throws AxelorException, IOException;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Notification;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
|
||||||
|
public interface NotificationService {
|
||||||
|
|
||||||
|
void populateNotificationItemList(Notification notification);
|
||||||
|
|
||||||
|
void validate(Notification notification) throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,262 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.Notification;
|
||||||
|
import com.axelor.apps.account.db.NotificationItem;
|
||||||
|
import com.axelor.apps.account.db.SubrogationRelease;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.NotificationRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.SubrogationReleaseRepository;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.db.JPA;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
|
public class NotificationServiceImpl implements NotificationService {
|
||||||
|
|
||||||
|
protected MoveService moveService;
|
||||||
|
protected ReconcileService reconcileService;
|
||||||
|
protected AccountConfigService accountConfigService;
|
||||||
|
protected SubrogationReleaseService subrogationReleaseService;
|
||||||
|
protected MoveRepository moveRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NotificationServiceImpl(
|
||||||
|
MoveService moveService,
|
||||||
|
ReconcileService reconcileService,
|
||||||
|
AccountConfigService accountConfigService,
|
||||||
|
SubrogationReleaseService subrogationReleaseService,
|
||||||
|
MoveRepository moveRepository) {
|
||||||
|
this.moveService = moveService;
|
||||||
|
this.reconcileService = reconcileService;
|
||||||
|
this.accountConfigService = accountConfigService;
|
||||||
|
this.subrogationReleaseService = subrogationReleaseService;
|
||||||
|
this.moveRepository = moveRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populateNotificationItemList(Notification notification) {
|
||||||
|
notification.clearNotificationItemList();
|
||||||
|
|
||||||
|
Comparator<Invoice> byInvoiceDate =
|
||||||
|
(i1, i2) -> i1.getInvoiceDate().compareTo(i2.getInvoiceDate());
|
||||||
|
Comparator<Invoice> byDueDate = (i1, i2) -> i1.getDueDate().compareTo(i2.getDueDate());
|
||||||
|
Comparator<Invoice> byInvoiceId = (i1, i2) -> i1.getInvoiceId().compareTo(i2.getInvoiceId());
|
||||||
|
|
||||||
|
List<Invoice> invoiceList = new ArrayList<Invoice>();
|
||||||
|
if (notification.getSubrogationRelease() != null) {
|
||||||
|
invoiceList =
|
||||||
|
notification
|
||||||
|
.getSubrogationRelease()
|
||||||
|
.getInvoiceSet()
|
||||||
|
.stream()
|
||||||
|
.sorted(byInvoiceDate.thenComparing(byDueDate).thenComparing(byInvoiceId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
for (Invoice invoice : invoiceList) {
|
||||||
|
if (invoice.getAmountRemaining().signum() > 0) {
|
||||||
|
notification.addNotificationItemListItem(createNotificationItem(invoice));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NotificationItem createNotificationItem(Invoice invoice) {
|
||||||
|
return new NotificationItem(invoice, invoice.getAmountRemaining());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void validate(Notification notification) throws AxelorException {
|
||||||
|
|
||||||
|
for (NotificationItem notificationItem : notification.getNotificationItemList()) {
|
||||||
|
this.createPaymentMove(notificationItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
notification.setStatusSelect(NotificationRepository.STATUS_VALIDATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Journal getJournal(AccountConfig accountConfig) throws AxelorException {
|
||||||
|
return accountConfigService.getAutoMiscOpeJournal(accountConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Account getAccount(AccountConfig accountConfig, NotificationItem notificationItem) {
|
||||||
|
Account account = accountConfig.getFactorCreditAccount();
|
||||||
|
if (notificationItem.getTypeSelect()
|
||||||
|
== NotificationRepository.TYPE_PAYMENT_TO_THE_FACTORE_AFTER_FACTORE_RETURN) {
|
||||||
|
account = accountConfig.getFactorDebitAccount();
|
||||||
|
}
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
protected Move createPaymentMove(NotificationItem notificationItem) throws AxelorException {
|
||||||
|
|
||||||
|
Notification notification = notificationItem.getNotification();
|
||||||
|
Invoice invoice = notificationItem.getInvoice();
|
||||||
|
Company company = invoice.getCompany();
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
Journal journal = getJournal(accountConfig);
|
||||||
|
|
||||||
|
SubrogationRelease subrogationRelease = getSubrogationRelease(notificationItem);
|
||||||
|
|
||||||
|
String origin = computeOrigin(subrogationRelease, invoice);
|
||||||
|
|
||||||
|
BigDecimal amountPaid = notificationItem.getAmountPaid();
|
||||||
|
|
||||||
|
if (amountPaid.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Move paymentMove =
|
||||||
|
moveService
|
||||||
|
.getMoveCreateService()
|
||||||
|
.createMove(
|
||||||
|
journal,
|
||||||
|
company,
|
||||||
|
company.getCurrency(),
|
||||||
|
invoice.getPartner(),
|
||||||
|
notification.getPaymentDate(),
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
MoveLine creditMoveLine, debitMoveLine;
|
||||||
|
|
||||||
|
Account account = getAccount(accountConfig, notificationItem);
|
||||||
|
|
||||||
|
debitMoveLine =
|
||||||
|
moveService
|
||||||
|
.getMoveLineService()
|
||||||
|
.createMoveLine(
|
||||||
|
paymentMove,
|
||||||
|
invoice.getPartner(),
|
||||||
|
account,
|
||||||
|
amountPaid,
|
||||||
|
true,
|
||||||
|
notification.getPaymentDate(),
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
origin,
|
||||||
|
invoice.getInvoiceId());
|
||||||
|
|
||||||
|
creditMoveLine =
|
||||||
|
moveService
|
||||||
|
.getMoveLineService()
|
||||||
|
.createMoveLine(
|
||||||
|
paymentMove,
|
||||||
|
invoice.getPartner(),
|
||||||
|
invoice.getPartnerAccount(),
|
||||||
|
amountPaid,
|
||||||
|
false,
|
||||||
|
notification.getPaymentDate(),
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
origin,
|
||||||
|
invoice.getInvoiceId());
|
||||||
|
|
||||||
|
paymentMove.addMoveLineListItem(debitMoveLine);
|
||||||
|
paymentMove.addMoveLineListItem(creditMoveLine);
|
||||||
|
paymentMove = moveRepository.save(paymentMove);
|
||||||
|
|
||||||
|
moveService.getMoveValidateService().validate(paymentMove);
|
||||||
|
|
||||||
|
MoveLine invoiceMoveLine = findInvoiceAccountMoveLine(invoice);
|
||||||
|
MoveLine subrogationReleaseMoveLine = findSubrogationReleaseAccountMoveLine(invoice);
|
||||||
|
|
||||||
|
if (invoiceMoveLine.getAmountRemaining().compareTo(BigDecimal.ZERO) == 1) {
|
||||||
|
reconcileService.reconcile(invoiceMoveLine, creditMoveLine, true, true);
|
||||||
|
if (subrogationReleaseMoveLine != null
|
||||||
|
&& notificationItem.getTypeSelect()
|
||||||
|
== NotificationRepository.TYPE_PAYMENT_TO_THE_FACTORE) {
|
||||||
|
reconcileService.reconcile(debitMoveLine, subrogationReleaseMoveLine, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationItem.setMove(paymentMove);
|
||||||
|
|
||||||
|
if (subrogationRelease != null) {
|
||||||
|
subrogationReleaseService.clear(subrogationRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String computeOrigin(SubrogationRelease subrogationRelease, Invoice invoice) {
|
||||||
|
|
||||||
|
return subrogationRelease != null
|
||||||
|
? subrogationRelease.getSequenceNumber()
|
||||||
|
: I18n.get("Payment notification") + " " + invoice.getInvoiceId();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SubrogationRelease getSubrogationRelease(NotificationItem notificationItem) {
|
||||||
|
|
||||||
|
Invoice invoice = notificationItem.getInvoice();
|
||||||
|
|
||||||
|
TypedQuery<SubrogationRelease> query =
|
||||||
|
JPA.em()
|
||||||
|
.createQuery(
|
||||||
|
"SELECT self FROM SubrogationRelease self JOIN self.invoiceSet invoices WHERE self.statusSelect = :statusSelect AND invoices.id IN (:invoiceId)",
|
||||||
|
SubrogationRelease.class);
|
||||||
|
query.setParameter("statusSelect", SubrogationReleaseRepository.STATUS_ACCOUNTED);
|
||||||
|
query.setParameter("invoiceId", invoice.getId());
|
||||||
|
|
||||||
|
List<SubrogationRelease> subrogationReleaseResultList = query.getResultList();
|
||||||
|
|
||||||
|
if (subrogationReleaseResultList != null && !subrogationReleaseResultList.isEmpty()) {
|
||||||
|
return subrogationReleaseResultList.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MoveLine findInvoiceAccountMoveLine(Invoice invoice) {
|
||||||
|
for (MoveLine moveLine : invoice.getMove().getMoveLineList()) {
|
||||||
|
if (moveLine.getAccount().equals(invoice.getPartnerAccount())) {
|
||||||
|
return moveLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MoveLine findSubrogationReleaseAccountMoveLine(Invoice invoice) throws AxelorException {
|
||||||
|
if (invoice.getSubrogationReleaseMove() != null) {
|
||||||
|
for (MoveLine moveLine : invoice.getSubrogationReleaseMove().getMoveLineList()) {
|
||||||
|
if (moveLine.getCredit().compareTo(BigDecimal.ZERO) == 1) {
|
||||||
|
return moveLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.FiscalPosition;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
|
||||||
|
public class PartnerAccountService {
|
||||||
|
|
||||||
|
public String getDefaultSpecificTaxNote(Partner partner) {
|
||||||
|
FiscalPosition fiscalPosition = partner.getFiscalPosition();
|
||||||
|
|
||||||
|
if (fiscalPosition == null || !fiscalPosition.getCustomerSpecificNote()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return fiscalPosition.getCustomerSpecificNoteText();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.PaymentMode;
|
||||||
|
import com.axelor.apps.account.db.PaymentSchedule;
|
||||||
|
import com.axelor.apps.account.db.PaymentScheduleLine;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface PaymentScheduleLineService {
|
||||||
|
|
||||||
|
PaymentScheduleLine createPaymentScheduleLine(
|
||||||
|
PaymentSchedule paymentSchedule,
|
||||||
|
BigDecimal inTaxAmount,
|
||||||
|
int scheduleLineSeq,
|
||||||
|
LocalDate scheduleDate);
|
||||||
|
|
||||||
|
List<PaymentScheduleLine> createPaymentScheduleLines(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a payment move for a payment schedule line with the given company bank details.
|
||||||
|
*
|
||||||
|
* @param paymentScheduleLine
|
||||||
|
* @param companyBankDetails
|
||||||
|
* @param paymentMode
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
Move createPaymentMove(
|
||||||
|
PaymentScheduleLine paymentScheduleLine,
|
||||||
|
BankDetails companyBankDetails,
|
||||||
|
PaymentMode paymentMode)
|
||||||
|
throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,362 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.DirectDebitManagement;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.PaymentMode;
|
||||||
|
import com.axelor.apps.account.db.PaymentSchedule;
|
||||||
|
import com.axelor.apps.account.db.PaymentScheduleLine;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentScheduleLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentScheduleRepository;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveToolService;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentModeService;
|
||||||
|
import com.axelor.apps.account.service.payment.PaymentService;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class PaymentScheduleLineServiceImpl implements PaymentScheduleLineService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected AppBaseService appBaseService;
|
||||||
|
protected PaymentScheduleService paymentScheduleService;
|
||||||
|
protected MoveService moveService;
|
||||||
|
protected PaymentModeService paymentModeService;
|
||||||
|
protected SequenceService sequenceService;
|
||||||
|
protected AccountingSituationService accountingSituationService;
|
||||||
|
protected MoveToolService moveToolService;
|
||||||
|
protected PaymentService paymentService;
|
||||||
|
protected MoveLineRepository moveLineRepo;
|
||||||
|
protected PaymentScheduleLineRepository paymentScheduleLineRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PaymentScheduleLineServiceImpl(
|
||||||
|
AppBaseService appBaseService,
|
||||||
|
PaymentScheduleService paymentScheduleService,
|
||||||
|
MoveService moveService,
|
||||||
|
PaymentModeService paymentModeService,
|
||||||
|
SequenceService sequenceService,
|
||||||
|
AccountingSituationService accountingSituationService,
|
||||||
|
MoveToolService moveToolService,
|
||||||
|
PaymentService paymentService,
|
||||||
|
MoveLineRepository moveLineRepo,
|
||||||
|
PaymentScheduleLineRepository paymentScheduleLineRepo) {
|
||||||
|
this.appBaseService = appBaseService;
|
||||||
|
this.paymentScheduleService = paymentScheduleService;
|
||||||
|
this.moveService = moveService;
|
||||||
|
this.paymentModeService = paymentModeService;
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
this.accountingSituationService = accountingSituationService;
|
||||||
|
this.moveToolService = moveToolService;
|
||||||
|
this.paymentService = paymentService;
|
||||||
|
this.moveLineRepo = moveLineRepo;
|
||||||
|
this.paymentScheduleLineRepo = paymentScheduleLineRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Création d'une ligne d'échéancier
|
||||||
|
*
|
||||||
|
* @param paymentSchedule L'échéancié attaché.
|
||||||
|
* @param invoiceTerm La facture d'échéance.
|
||||||
|
* @param scheduleLineSeq Le numéro d'échéance.
|
||||||
|
* @param scheduleDate La date d'échéance.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PaymentScheduleLine createPaymentScheduleLine(
|
||||||
|
PaymentSchedule paymentSchedule,
|
||||||
|
BigDecimal inTaxAmount,
|
||||||
|
int scheduleLineSeq,
|
||||||
|
LocalDate scheduleDate) {
|
||||||
|
|
||||||
|
PaymentScheduleLine paymentScheduleLine = new PaymentScheduleLine();
|
||||||
|
paymentScheduleLine.setScheduleLineSeq(scheduleLineSeq);
|
||||||
|
paymentScheduleLine.setScheduleDate(scheduleDate);
|
||||||
|
paymentScheduleLine.setInTaxAmount(inTaxAmount);
|
||||||
|
paymentScheduleLine.setStatusSelect(PaymentScheduleLineRepository.STATUS_DRAFT);
|
||||||
|
|
||||||
|
if (paymentSchedule != null) {
|
||||||
|
paymentSchedule.addPaymentScheduleLineListItem(paymentScheduleLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Création de la ligne de l'échéancier numéro {} pour la date du {} et la somme de {}",
|
||||||
|
new Object[] {
|
||||||
|
paymentScheduleLine.getScheduleLineSeq(),
|
||||||
|
paymentScheduleLine.getScheduleDate(),
|
||||||
|
paymentScheduleLine.getInTaxAmount()
|
||||||
|
});
|
||||||
|
|
||||||
|
return paymentScheduleLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* En fonction des infos d'entête d'un échéancier, crée les lignes d'échéances
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<PaymentScheduleLine> createPaymentScheduleLines(PaymentSchedule paymentSchedule) {
|
||||||
|
|
||||||
|
List<PaymentScheduleLine> paymentScheduleLines = new ArrayList<PaymentScheduleLine>();
|
||||||
|
|
||||||
|
int nbrTerm = paymentSchedule.getNbrTerm();
|
||||||
|
|
||||||
|
BigDecimal inTaxAmount = paymentSchedule.getInTaxAmount();
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Création de lignes pour l'échéancier numéro {} (nombre d'échéance : {}, montant : {})",
|
||||||
|
new Object[] {paymentSchedule.getPaymentScheduleSeq(), nbrTerm, inTaxAmount});
|
||||||
|
|
||||||
|
if (nbrTerm > 0 && inTaxAmount.compareTo(BigDecimal.ZERO) == 1) {
|
||||||
|
|
||||||
|
BigDecimal termAmount =
|
||||||
|
inTaxAmount.divide(new BigDecimal(nbrTerm), 2, RoundingMode.HALF_EVEN);
|
||||||
|
BigDecimal cumul = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
for (int i = 1; i < nbrTerm + 1; i++) {
|
||||||
|
|
||||||
|
if (i == nbrTerm) {
|
||||||
|
termAmount = inTaxAmount.subtract(cumul);
|
||||||
|
} else {
|
||||||
|
cumul = cumul.add(termAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentScheduleLines.add(
|
||||||
|
this.createPaymentScheduleLine(
|
||||||
|
paymentSchedule, termAmount, i, paymentSchedule.getStartDate().plusMonths(i - 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentScheduleLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public Move createPaymentMove(
|
||||||
|
PaymentScheduleLine paymentScheduleLine,
|
||||||
|
BankDetails companyBankDetails,
|
||||||
|
PaymentMode paymentMode)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Preconditions.checkNotNull(paymentScheduleLine);
|
||||||
|
Preconditions.checkNotNull(companyBankDetails);
|
||||||
|
|
||||||
|
PaymentSchedule paymentSchedule = paymentScheduleLine.getPaymentSchedule();
|
||||||
|
Company company = paymentSchedule.getCompany();
|
||||||
|
Partner partner = paymentSchedule.getPartner();
|
||||||
|
Journal journal =
|
||||||
|
paymentModeService.getPaymentModeJournal(paymentMode, company, companyBankDetails);
|
||||||
|
BigDecimal amount = paymentScheduleLine.getInTaxAmount();
|
||||||
|
String name = paymentScheduleLine.getName();
|
||||||
|
LocalDate todayDate = appBaseService.getTodayDate();
|
||||||
|
Account account = accountingSituationService.getCustomerAccount(partner, company);
|
||||||
|
|
||||||
|
Move move =
|
||||||
|
moveService
|
||||||
|
.getMoveCreateService()
|
||||||
|
.createMove(
|
||||||
|
journal,
|
||||||
|
company,
|
||||||
|
null,
|
||||||
|
partner,
|
||||||
|
paymentMode,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
|
||||||
|
MoveLine creditMoveLine =
|
||||||
|
moveService
|
||||||
|
.getMoveLineService()
|
||||||
|
.createMoveLine(move, partner, account, amount, false, todayDate, 1, name, null);
|
||||||
|
move.addMoveLineListItem(creditMoveLine);
|
||||||
|
creditMoveLine = moveLineRepo.save(creditMoveLine);
|
||||||
|
|
||||||
|
Account paymentModeAccount =
|
||||||
|
paymentModeService.getPaymentModeAccount(paymentMode, company, companyBankDetails);
|
||||||
|
MoveLine debitMoveLine =
|
||||||
|
moveService
|
||||||
|
.getMoveLineService()
|
||||||
|
.createMoveLine(
|
||||||
|
move, partner, paymentModeAccount, amount, true, todayDate, 2, name, null);
|
||||||
|
move.addMoveLineListItem(debitMoveLine);
|
||||||
|
debitMoveLine = moveLineRepo.save(debitMoveLine);
|
||||||
|
|
||||||
|
moveService.getMoveValidateService().validate(move);
|
||||||
|
|
||||||
|
// Reconcile
|
||||||
|
if (paymentSchedule.getTypeSelect() == PaymentScheduleRepository.TYPE_TERMS
|
||||||
|
&& paymentSchedule.getInvoiceSet() != null) {
|
||||||
|
List<MoveLine> debitMoveLineList =
|
||||||
|
paymentSchedule
|
||||||
|
.getInvoiceSet()
|
||||||
|
.stream()
|
||||||
|
.sorted(Comparator.comparing(Invoice::getDueDate))
|
||||||
|
.map(invoice -> moveService.getMoveLineService().getDebitCustomerMoveLine(invoice))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (moveToolService.isSameAccount(debitMoveLineList, account)) {
|
||||||
|
List<MoveLine> creditMoveLineList = Lists.newArrayList(creditMoveLine);
|
||||||
|
paymentService.useExcessPaymentOnMoveLines(debitMoveLineList, creditMoveLineList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentScheduleLine.setDirectDebitAmount(amount);
|
||||||
|
paymentScheduleLine.setInTaxAmountPaid(amount);
|
||||||
|
paymentScheduleLine.setAdvanceOrPaymentMove(move);
|
||||||
|
paymentScheduleLine.setAdvanceMoveLine(creditMoveLine);
|
||||||
|
paymentScheduleLine.setStatusSelect(PaymentScheduleLineRepository.STATUS_VALIDATED);
|
||||||
|
|
||||||
|
paymentScheduleService.closePaymentScheduleIfAllPaid(paymentSchedule);
|
||||||
|
|
||||||
|
return move;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant d'assigner un numéro de prélèvement à l'échéance à prélever Si plusieurs
|
||||||
|
* échéance d'un même échéancier sont à prélever, alors on utilise un objet de gestion de
|
||||||
|
* prélèvement encadrant l'ensemble des échéances en question Sinon on assigne simplement un
|
||||||
|
* numéro de prélèvement à l'échéance
|
||||||
|
*
|
||||||
|
* @param paymentScheduleLineList Une liste d'échéance à prélever
|
||||||
|
* @param paymentScheduleLine L'échéance traité
|
||||||
|
* @param company Une société
|
||||||
|
* @param paymentMode TODO
|
||||||
|
* @param journal Un journal (prélèvement mensu masse ou grand compte)
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
protected void setDebitNumber(
|
||||||
|
List<PaymentScheduleLine> paymentScheduleLineList,
|
||||||
|
PaymentScheduleLine paymentScheduleLine,
|
||||||
|
Company company,
|
||||||
|
PaymentMode paymentMode)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
if (hasOtherPaymentScheduleLine(paymentScheduleLineList, paymentScheduleLine)) {
|
||||||
|
DirectDebitManagement directDebitManagement =
|
||||||
|
getDirectDebitManagement(paymentScheduleLineList, paymentScheduleLine);
|
||||||
|
if (directDebitManagement == null) {
|
||||||
|
directDebitManagement =
|
||||||
|
createDirectDebitManagement(getDirectDebitSequence(company, paymentMode), company);
|
||||||
|
}
|
||||||
|
paymentScheduleLine.setDirectDebitManagement(directDebitManagement);
|
||||||
|
directDebitManagement.getPaymentScheduleLineList().add(paymentScheduleLine);
|
||||||
|
} else {
|
||||||
|
paymentScheduleLine.setDebitNumber(getDirectDebitSequence(company, paymentMode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setDebitNumber(PaymentScheduleLine paymentScheduleLine, PaymentMode paymentMode)
|
||||||
|
throws AxelorException {
|
||||||
|
PaymentSchedule paymentSchedule = paymentScheduleLine.getPaymentSchedule();
|
||||||
|
List<PaymentScheduleLine> paymentScheduleLineList =
|
||||||
|
paymentSchedule.getPaymentScheduleLineList();
|
||||||
|
Company company = paymentSchedule.getCompany();
|
||||||
|
setDebitNumber(paymentScheduleLineList, paymentScheduleLine, company, paymentMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Y a-t-il d'autres échéance a exporter pour le même payeur ?
|
||||||
|
*
|
||||||
|
* @param pslList : une liste d'échéance
|
||||||
|
* @param psl
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected boolean hasOtherPaymentScheduleLine(
|
||||||
|
List<PaymentScheduleLine> pslList, PaymentScheduleLine psl) {
|
||||||
|
int i = 0;
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : pslList) {
|
||||||
|
paymentScheduleLine = paymentScheduleLineRepo.find(paymentScheduleLine.getId());
|
||||||
|
if (psl.getPaymentSchedule().equals(paymentScheduleLine.getPaymentSchedule())) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de récupérer l'objet de gestion déjà créé lors du prélèvement d'une autre
|
||||||
|
* échéance
|
||||||
|
*
|
||||||
|
* @param pslList La liste d'échéance à prélever
|
||||||
|
* @param psl L'échéance à prélever
|
||||||
|
* @return L'objet de gestion trouvé
|
||||||
|
*/
|
||||||
|
protected DirectDebitManagement getDirectDebitManagement(
|
||||||
|
List<PaymentScheduleLine> pslList, PaymentScheduleLine psl) {
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : pslList) {
|
||||||
|
paymentScheduleLine = paymentScheduleLineRepo.find(paymentScheduleLine.getId());
|
||||||
|
if (psl.getPaymentSchedule().equals(paymentScheduleLine.getPaymentSchedule())) {
|
||||||
|
if (paymentScheduleLine.getDirectDebitManagement() != null) {
|
||||||
|
return paymentScheduleLine.getDirectDebitManagement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de créer un objet de gestion de prélèvement
|
||||||
|
*
|
||||||
|
* @param sequence La séquence de prélèvement à utiliser
|
||||||
|
* @param company Une société
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected DirectDebitManagement createDirectDebitManagement(String sequence, Company company) {
|
||||||
|
DirectDebitManagement directDebitManagement = new DirectDebitManagement();
|
||||||
|
directDebitManagement.setDebitNumber(sequence);
|
||||||
|
directDebitManagement.setInvoiceSet(new HashSet<Invoice>());
|
||||||
|
directDebitManagement.setPaymentScheduleLineList(new ArrayList<PaymentScheduleLine>());
|
||||||
|
directDebitManagement.setCompany(company);
|
||||||
|
return directDebitManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDirectDebitSequence(Company company, PaymentMode paymentMode)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
// TODO manage multi bank
|
||||||
|
|
||||||
|
return sequenceService.getSequenceNumber(
|
||||||
|
paymentModeService.getPaymentModeSequence(paymentMode, company, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.PaymentMode;
|
||||||
|
import com.axelor.apps.account.db.PaymentSchedule;
|
||||||
|
import com.axelor.apps.account.db.PaymentScheduleLine;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface PaymentScheduleService {
|
||||||
|
PaymentSchedule createPaymentSchedule(
|
||||||
|
Partner partner, Company company, Set<Invoice> invoices, LocalDate startDate, int nbrTerm)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
PaymentSchedule createPaymentSchedule(
|
||||||
|
Partner partner,
|
||||||
|
Invoice invoice,
|
||||||
|
Company company,
|
||||||
|
LocalDate date,
|
||||||
|
LocalDate startDate,
|
||||||
|
int nbrTerm,
|
||||||
|
BankDetails bankDetails,
|
||||||
|
PaymentMode paymentMode)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
String getPaymentScheduleSequence(Company company) throws AxelorException;
|
||||||
|
|
||||||
|
BigDecimal getInvoiceTermTotal(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
void updatePaymentSchedule(PaymentSchedule paymentSchedule, BigDecimal inTaxTotal);
|
||||||
|
|
||||||
|
PaymentSchedule createPaymentSchedule(
|
||||||
|
Partner partner,
|
||||||
|
Company company,
|
||||||
|
LocalDate date,
|
||||||
|
LocalDate firstTermDate,
|
||||||
|
BigDecimal initialInTaxAmount,
|
||||||
|
int nbrTerm,
|
||||||
|
BankDetails bankDetails,
|
||||||
|
PaymentMode paymentMode)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
List<MoveLine> getPaymentSchedulerMoveLineToPay(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
void validatePaymentSchedule(PaymentSchedule paymentSchedule) throws AxelorException;
|
||||||
|
|
||||||
|
void updateInvoices(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
void updateInvoice(Invoice invoice, PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
void cancelPaymentSchedule(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
boolean isLastSchedule(PaymentScheduleLine paymentScheduleLine);
|
||||||
|
|
||||||
|
void closePaymentSchedule(PaymentSchedule paymentSchedule) throws AxelorException;
|
||||||
|
|
||||||
|
void closePaymentScheduleIfAllPaid(PaymentSchedule paymentSchedule) throws AxelorException;
|
||||||
|
|
||||||
|
LocalDate getMostOldDatePaymentScheduleLine(List<PaymentScheduleLine> paymentScheduleLineList);
|
||||||
|
|
||||||
|
LocalDate getMostRecentDatePaymentScheduleLine(List<PaymentScheduleLine> paymentScheduleLineList);
|
||||||
|
|
||||||
|
void createPaymentScheduleLines(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
void initCollection(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
void toCancelPaymentSchedule(PaymentSchedule paymentSchedule);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get partner's bank details.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
BankDetails getBankDetails(PaymentSchedule paymentSchedule) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check total line amount.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
void checkTotalLineAmount(PaymentSchedule paymentSchedule) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get next payment schedule line sequence number.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getNextScheduleLineSeq(PaymentSchedule paymentSchedule);
|
||||||
|
}
|
||||||
@ -0,0 +1,608 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.PaymentMode;
|
||||||
|
import com.axelor.apps.account.db.PaymentSchedule;
|
||||||
|
import com.axelor.apps.account.db.PaymentScheduleLine;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentScheduleLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.PaymentScheduleRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountService;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.PartnerService;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class PaymentScheduleServiceImpl implements PaymentScheduleService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected PaymentScheduleLineService paymentScheduleLineService;
|
||||||
|
protected PaymentScheduleLineRepository paymentScheduleLineRepo;
|
||||||
|
protected SequenceService sequenceService;
|
||||||
|
protected PaymentScheduleRepository paymentScheduleRepo;
|
||||||
|
protected PartnerService partnerService;
|
||||||
|
|
||||||
|
protected AppAccountService appAccountService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PaymentScheduleServiceImpl(
|
||||||
|
AppAccountService appAccountService,
|
||||||
|
PaymentScheduleLineService paymentScheduleLineService,
|
||||||
|
PaymentScheduleLineRepository paymentScheduleLineRepo,
|
||||||
|
SequenceService sequenceService,
|
||||||
|
PaymentScheduleRepository paymentScheduleRepo,
|
||||||
|
PartnerService partnerService) {
|
||||||
|
this.paymentScheduleLineService = paymentScheduleLineService;
|
||||||
|
this.paymentScheduleLineRepo = paymentScheduleLineRepo;
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
this.paymentScheduleRepo = paymentScheduleRepo;
|
||||||
|
this.partnerService = partnerService;
|
||||||
|
|
||||||
|
this.appAccountService = appAccountService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Création d'un échéancier sans ces lignes.
|
||||||
|
*
|
||||||
|
* @param partner Le tiers.
|
||||||
|
* @param invoices Collection de factures.
|
||||||
|
* @param company La société.
|
||||||
|
* @param startDate Date de première échéance.
|
||||||
|
* @param nbrTerm Nombre d'échéances.
|
||||||
|
* @return L'échéancier créé.
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PaymentSchedule createPaymentSchedule(
|
||||||
|
Partner partner, Company company, Set<Invoice> invoices, LocalDate startDate, int nbrTerm)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Invoice invoice = null;
|
||||||
|
|
||||||
|
PaymentSchedule paymentSchedule =
|
||||||
|
this.createPaymentSchedule(
|
||||||
|
partner,
|
||||||
|
invoice,
|
||||||
|
company,
|
||||||
|
appAccountService.getTodayDate(),
|
||||||
|
startDate,
|
||||||
|
nbrTerm,
|
||||||
|
partnerService.getDefaultBankDetails(partner),
|
||||||
|
partner.getInPaymentMode());
|
||||||
|
|
||||||
|
paymentSchedule.getInvoiceSet().addAll(invoices);
|
||||||
|
|
||||||
|
return paymentSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Création d'un échéancier sans ces lignes.
|
||||||
|
*
|
||||||
|
* @param partner Le tiers.
|
||||||
|
* @param invoice Facture globale permettant de définir la facture pour une échéance. L'échéancier
|
||||||
|
* est automatiquement associé à la facture si celle-ci existe.
|
||||||
|
* @param company La société.
|
||||||
|
* @param date Date de création.
|
||||||
|
* @param startDate Date de première échéance.
|
||||||
|
* @param nbrTerm Nombre d'échéances.
|
||||||
|
* @param bankDetails RIB.
|
||||||
|
* @param paymentMode Mode de paiement.
|
||||||
|
* @param payerPartner Tiers payeur.
|
||||||
|
* @param type Type de l'échéancier. <code>0 = paiement</code> <code>1 = mensu masse</code> <code>
|
||||||
|
* 2 = mensu grand-compte</code>
|
||||||
|
* @return L'échéancier créé.
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PaymentSchedule createPaymentSchedule(
|
||||||
|
Partner partner,
|
||||||
|
Invoice invoice,
|
||||||
|
Company company,
|
||||||
|
LocalDate date,
|
||||||
|
LocalDate startDate,
|
||||||
|
int nbrTerm,
|
||||||
|
BankDetails bankDetails,
|
||||||
|
PaymentMode paymentMode)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
PaymentSchedule paymentSchedule = new PaymentSchedule();
|
||||||
|
|
||||||
|
paymentSchedule.setCompany(company);
|
||||||
|
paymentSchedule.setPaymentScheduleSeq(this.getPaymentScheduleSequence(company));
|
||||||
|
paymentSchedule.setCreationDate(date);
|
||||||
|
paymentSchedule.setStartDate(startDate);
|
||||||
|
paymentSchedule.setNbrTerm(nbrTerm);
|
||||||
|
paymentSchedule.setBankDetails(bankDetails);
|
||||||
|
paymentSchedule.setPaymentMode(paymentMode);
|
||||||
|
paymentSchedule.setPartner(partner);
|
||||||
|
|
||||||
|
if (paymentSchedule.getInvoiceSet() == null) {
|
||||||
|
paymentSchedule.setInvoiceSet(new HashSet<Invoice>());
|
||||||
|
} else {
|
||||||
|
paymentSchedule.getInvoiceSet().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invoice != null) {
|
||||||
|
paymentSchedule.addInvoiceSetItem(invoice);
|
||||||
|
invoice.setPaymentSchedule(paymentSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de tester et de récupérer une séquence de prélèvement
|
||||||
|
*
|
||||||
|
* @param company Une société
|
||||||
|
* @param journal Un journal
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getPaymentScheduleSequence(Company company) throws AxelorException {
|
||||||
|
String seq = sequenceService.getSequenceNumber(SequenceRepository.PAYMENT_SCHEDULE, company);
|
||||||
|
if (seq == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
"%s :\n" + I18n.get(IExceptionMessage.PAYMENT_SCHEDULE_5),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtenir le total des factures des lignes d'un échéancier.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule L'échéancier cible.
|
||||||
|
* @return Le somme des montants TTC des lignes de l'échéancier.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public BigDecimal getInvoiceTermTotal(PaymentSchedule paymentSchedule) {
|
||||||
|
|
||||||
|
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
if (paymentSchedule != null
|
||||||
|
&& paymentSchedule.getPaymentScheduleLineList() != null
|
||||||
|
&& !paymentSchedule.getPaymentScheduleLineList().isEmpty()) {
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentSchedule.getPaymentScheduleLineList()) {
|
||||||
|
if (paymentScheduleLine.getInTaxAmount() != null) {
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Somme TTC des lignes de l'échéancier {} : total = {}, ajout = {}",
|
||||||
|
new Object[] {
|
||||||
|
paymentSchedule.getPaymentScheduleSeq(),
|
||||||
|
totalAmount,
|
||||||
|
paymentScheduleLine.getInTaxAmount()
|
||||||
|
});
|
||||||
|
|
||||||
|
totalAmount = totalAmount.add(paymentScheduleLine.getInTaxAmount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Obtention de la somme TTC des lignes de l'échéancier {} : {}",
|
||||||
|
new Object[] {paymentSchedule.getPaymentScheduleSeq(), totalAmount});
|
||||||
|
|
||||||
|
return totalAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mise à jour d'un échéancier avec un nouveau montant d'échéance.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule L'échéancier cible.
|
||||||
|
* @param inTaxTotal Nouveau montant d'une échéance.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void updatePaymentSchedule(PaymentSchedule paymentSchedule, BigDecimal inTaxTotal) {
|
||||||
|
|
||||||
|
log.debug(
|
||||||
|
"Mise à jour de l'échéancier {} : {}",
|
||||||
|
new Object[] {paymentSchedule.getPaymentScheduleSeq(), inTaxTotal});
|
||||||
|
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentSchedule.getPaymentScheduleLineList()) {
|
||||||
|
|
||||||
|
if (paymentScheduleLine.getStatusSelect() == PaymentScheduleLineRepository.STATUS_IN_PROGRESS
|
||||||
|
&& !paymentScheduleLine.getRejectedOk()) {
|
||||||
|
|
||||||
|
log.debug("Mise à jour de la ligne {} ", paymentScheduleLine.getName());
|
||||||
|
|
||||||
|
paymentScheduleLine.setInTaxAmount(inTaxTotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentScheduleRepo.save(paymentSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Création d'un échéancier avec ces lignes.
|
||||||
|
*
|
||||||
|
* @param company La société.
|
||||||
|
* @param date Date de création.
|
||||||
|
* @param firstTermDate Date de première échéance.
|
||||||
|
* @param initialInTaxAmount Montant d'une échéance.
|
||||||
|
* @param nbrTerm Nombre d'échéances.
|
||||||
|
* @param bankDetails RIB.
|
||||||
|
* @param paymentMode Mode de paiement.
|
||||||
|
* @param payerPartner Tiers payeur.
|
||||||
|
* @return L'échéancier créé.
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PaymentSchedule createPaymentSchedule(
|
||||||
|
Partner partner,
|
||||||
|
Company company,
|
||||||
|
LocalDate date,
|
||||||
|
LocalDate firstTermDate,
|
||||||
|
BigDecimal initialInTaxAmount,
|
||||||
|
int nbrTerm,
|
||||||
|
BankDetails bankDetails,
|
||||||
|
PaymentMode paymentMode)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
Invoice invoice = null;
|
||||||
|
PaymentSchedule paymentSchedule =
|
||||||
|
this.createPaymentSchedule(
|
||||||
|
partner, invoice, company, date, firstTermDate, nbrTerm, bankDetails, paymentMode);
|
||||||
|
|
||||||
|
paymentSchedule.setPaymentScheduleLineList(new ArrayList<PaymentScheduleLine>());
|
||||||
|
|
||||||
|
for (int term = 1; term < nbrTerm + 1; term++) {
|
||||||
|
paymentSchedule
|
||||||
|
.getPaymentScheduleLineList()
|
||||||
|
.add(
|
||||||
|
paymentScheduleLineService.createPaymentScheduleLine(
|
||||||
|
paymentSchedule, initialInTaxAmount, term, firstTermDate.plusMonths(term - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentSchedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to get the movelines to be paid based on a paymentSchedule It loops on the
|
||||||
|
* invoice M2M content and gets the movelines which are to pay
|
||||||
|
*
|
||||||
|
* @param ps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<MoveLine> getPaymentSchedulerMoveLineToPay(PaymentSchedule paymentSchedule) {
|
||||||
|
log.debug("In getPaymentSchedulerMoveLineToPay ....");
|
||||||
|
List<MoveLine> moveLines = new ArrayList<MoveLine>();
|
||||||
|
for (Invoice invoice : paymentSchedule.getInvoiceSet()) {
|
||||||
|
if (invoice.getCompanyInTaxTotalRemaining().compareTo(BigDecimal.ZERO) > 0
|
||||||
|
&& invoice.getMove() != null
|
||||||
|
&& invoice.getMove().getMoveLineList() != null) {
|
||||||
|
for (MoveLine moveLine : invoice.getMove().getMoveLineList()) {
|
||||||
|
if (moveLine.getAccount().getUseForPartnerBalance()
|
||||||
|
&& moveLine.getAmountRemaining().compareTo(BigDecimal.ZERO) > 0
|
||||||
|
&& moveLine.getDebit().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
moveLines.add(moveLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("End getPaymentSchedulerMoveLineToPay.");
|
||||||
|
return moveLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkTotalLineAmount(PaymentSchedule paymentSchedule) throws AxelorException {
|
||||||
|
BigDecimal total = getInvoiceTermTotal(paymentSchedule);
|
||||||
|
|
||||||
|
if (total.compareTo(paymentSchedule.getInTaxAmount()) != 0) {
|
||||||
|
throw new AxelorException(
|
||||||
|
paymentSchedule,
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.PAYMENT_SCHEDULE_LINE_AMOUNT_MISMATCH),
|
||||||
|
total,
|
||||||
|
paymentSchedule.getInTaxAmount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de valider un échéancier.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void validatePaymentSchedule(PaymentSchedule paymentSchedule) throws AxelorException {
|
||||||
|
|
||||||
|
log.debug("Validation de l'échéancier {}", paymentSchedule.getPaymentScheduleSeq());
|
||||||
|
|
||||||
|
if (paymentSchedule.getPaymentScheduleLineList() == null
|
||||||
|
|| paymentSchedule.getPaymentScheduleLineList().isEmpty()) {
|
||||||
|
throw new AxelorException(
|
||||||
|
paymentSchedule,
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.PAYMENT_SCHEDULE_6),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
paymentSchedule.getPaymentScheduleSeq());
|
||||||
|
}
|
||||||
|
|
||||||
|
checkTotalLineAmount(paymentSchedule);
|
||||||
|
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentSchedule.getPaymentScheduleLineList()) {
|
||||||
|
paymentScheduleLine.setStatusSelect(PaymentScheduleLineRepository.STATUS_IN_PROGRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateInvoices(paymentSchedule);
|
||||||
|
|
||||||
|
paymentSchedule.setStatusSelect(PaymentScheduleRepository.STATUS_CONFIRMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateInvoices(PaymentSchedule paymentSchedule) {
|
||||||
|
|
||||||
|
if (paymentSchedule.getInvoiceSet() != null) {
|
||||||
|
|
||||||
|
List<MoveLine> moveLineInvoiceToPay = this.getPaymentSchedulerMoveLineToPay(paymentSchedule);
|
||||||
|
|
||||||
|
for (MoveLine moveLineInvoice : moveLineInvoiceToPay) {
|
||||||
|
|
||||||
|
moveLineInvoice.getMove().setIgnoreInDebtRecoveryOk(true);
|
||||||
|
this.updateInvoice(moveLineInvoice.getMove().getInvoice(), paymentSchedule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateInvoice(Invoice invoice, PaymentSchedule paymentSchedule) {
|
||||||
|
|
||||||
|
invoice.setSchedulePaymentOk(true);
|
||||||
|
invoice.setPaymentSchedule(paymentSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui annule un échéancier
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void cancelPaymentSchedule(PaymentSchedule paymentSchedule) {
|
||||||
|
|
||||||
|
// L'échéancier est passé à annulé
|
||||||
|
paymentSchedule.setStatusSelect(PaymentScheduleRepository.STATUS_CANCELED);
|
||||||
|
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentSchedule.getPaymentScheduleLineList()) {
|
||||||
|
|
||||||
|
// Si l'échéance n'est pas complètement payée
|
||||||
|
if (paymentScheduleLine.getInTaxAmountPaid().compareTo(paymentScheduleLine.getInTaxAmount())
|
||||||
|
!= 0) {
|
||||||
|
|
||||||
|
// L'échéance est passée à cloturé
|
||||||
|
paymentScheduleLine.setStatusSelect(PaymentScheduleLineRepository.STATUS_CLOSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Invoice invoice : paymentSchedule.getInvoiceSet()) {
|
||||||
|
// L'échéancier n'est plus selectionné sur la facture
|
||||||
|
invoice.setPaymentSchedule(null);
|
||||||
|
|
||||||
|
// L'échéancier est assigné dans un nouveau champs afin de garder un lien invisble pour
|
||||||
|
// l'utilisateur, mais utilisé pour le passage en irrécouvrable
|
||||||
|
invoice.setCanceledPaymentSchedule(paymentSchedule);
|
||||||
|
invoice.setSchedulePaymentOk(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode permettant de savoir si l'échéance passée en paramètre est la dernière de l'échéancier
|
||||||
|
*
|
||||||
|
* @param paymentScheduleLine
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isLastSchedule(PaymentScheduleLine paymentScheduleLine) {
|
||||||
|
if (paymentScheduleLine != null) {
|
||||||
|
if (paymentScheduleLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.paymentSchedule = ?1 and self.scheduleDate > ?2 and self.statusSelect = ?3",
|
||||||
|
paymentScheduleLine.getPaymentSchedule(),
|
||||||
|
paymentScheduleLine.getScheduleDate(),
|
||||||
|
PaymentScheduleLineRepository.STATUS_IN_PROGRESS)
|
||||||
|
.fetchOne()
|
||||||
|
== null) {
|
||||||
|
log.debug("Dernière échéance");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de passer les statuts des lignes d'échéances et de l'échéancier à 'clo' ie
|
||||||
|
* cloturé
|
||||||
|
*
|
||||||
|
* @param invoice Une facture de fin de cycle
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void closePaymentSchedule(PaymentSchedule paymentSchedule) throws AxelorException {
|
||||||
|
|
||||||
|
log.debug("Cloture de l'échéancier");
|
||||||
|
|
||||||
|
// On récupère un statut cloturé, afin de pouvoir changer l'état des lignes d'échéanciers
|
||||||
|
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentSchedule.getPaymentScheduleLineList()) {
|
||||||
|
paymentScheduleLine.setStatusSelect(PaymentScheduleLineRepository.STATUS_CLOSED);
|
||||||
|
}
|
||||||
|
paymentSchedule.setStatusSelect(PaymentScheduleRepository.STATUS_CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close payment schedule if all paid.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void closePaymentScheduleIfAllPaid(PaymentSchedule paymentSchedule)
|
||||||
|
throws AxelorException {
|
||||||
|
if (paymentSchedule.getPaymentScheduleLineList() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentSchedule.getPaymentScheduleLineList()) {
|
||||||
|
if (paymentScheduleLine.getStatusSelect() < PaymentScheduleLineRepository.STATUS_VALIDATED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentSchedule.setStatusSelect(PaymentScheduleRepository.STATUS_CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDate getMostOldDatePaymentScheduleLine(
|
||||||
|
List<PaymentScheduleLine> paymentScheduleLineList) {
|
||||||
|
LocalDate minPaymentScheduleLineDate = LocalDate.now();
|
||||||
|
|
||||||
|
if (paymentScheduleLineList != null && !paymentScheduleLineList.isEmpty()) {
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentScheduleLineList) {
|
||||||
|
if (minPaymentScheduleLineDate.isAfter(paymentScheduleLine.getScheduleDate())) {
|
||||||
|
minPaymentScheduleLineDate = paymentScheduleLine.getScheduleDate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
minPaymentScheduleLineDate = null;
|
||||||
|
}
|
||||||
|
return minPaymentScheduleLineDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDate getMostRecentDatePaymentScheduleLine(
|
||||||
|
List<PaymentScheduleLine> paymentScheduleLineList) {
|
||||||
|
LocalDate minPaymentScheduleLineDate = LocalDate.now();
|
||||||
|
|
||||||
|
if (paymentScheduleLineList != null && !paymentScheduleLineList.isEmpty()) {
|
||||||
|
for (PaymentScheduleLine paymentScheduleLine : paymentScheduleLineList) {
|
||||||
|
if (minPaymentScheduleLineDate.isBefore(paymentScheduleLine.getScheduleDate())) {
|
||||||
|
minPaymentScheduleLineDate = paymentScheduleLine.getScheduleDate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
minPaymentScheduleLineDate = null;
|
||||||
|
}
|
||||||
|
return minPaymentScheduleLineDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transactional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Créer des lignes d'échéancier à partir des lignes de factures de celui-ci.
|
||||||
|
*
|
||||||
|
* @param paymentSchedule
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void createPaymentScheduleLines(PaymentSchedule paymentSchedule) {
|
||||||
|
|
||||||
|
this.initCollection(paymentSchedule);
|
||||||
|
|
||||||
|
paymentSchedule
|
||||||
|
.getPaymentScheduleLineList()
|
||||||
|
.addAll(paymentScheduleLineService.createPaymentScheduleLines(paymentSchedule));
|
||||||
|
paymentScheduleRepo.save(paymentSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initCollection(PaymentSchedule paymentSchedule) {
|
||||||
|
|
||||||
|
if (paymentSchedule.getPaymentScheduleLineList() == null) {
|
||||||
|
paymentSchedule.setPaymentScheduleLineList(new ArrayList<PaymentScheduleLine>());
|
||||||
|
} else {
|
||||||
|
paymentSchedule.getPaymentScheduleLineList().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void toCancelPaymentSchedule(PaymentSchedule paymentSchedule) {
|
||||||
|
this.cancelPaymentSchedule(paymentSchedule);
|
||||||
|
paymentScheduleRepo.save(paymentSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BankDetails getBankDetails(PaymentSchedule paymentSchedule) throws AxelorException {
|
||||||
|
BankDetails bankDetails = paymentSchedule.getBankDetails();
|
||||||
|
|
||||||
|
if (bankDetails != null) {
|
||||||
|
return bankDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
Partner partner = paymentSchedule.getPartner();
|
||||||
|
Preconditions.checkNotNull(partner);
|
||||||
|
bankDetails = partnerService.getDefaultBankDetails(partner);
|
||||||
|
|
||||||
|
if (bankDetails != null) {
|
||||||
|
return bankDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AxelorException(
|
||||||
|
partner,
|
||||||
|
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||||
|
I18n.get(IExceptionMessage.PARTNER_BANK_DETAILS_MISSING),
|
||||||
|
partner.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNextScheduleLineSeq(PaymentSchedule paymentSchedule) {
|
||||||
|
List<PaymentScheduleLine> paymentScheduleLines =
|
||||||
|
MoreObjects.firstNonNull(
|
||||||
|
paymentSchedule.getPaymentScheduleLineList(), Collections.emptyList());
|
||||||
|
int currentMaxSequenceNumber =
|
||||||
|
paymentScheduleLines
|
||||||
|
.stream()
|
||||||
|
.mapToInt(PaymentScheduleLine::getScheduleLineSeq)
|
||||||
|
.max()
|
||||||
|
.orElse(0);
|
||||||
|
return currentMaxSequenceNumber + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.base.db.Period;
|
||||||
|
import com.axelor.db.Query;
|
||||||
|
|
||||||
|
public interface PeriodServiceAccount {
|
||||||
|
|
||||||
|
public Query<Move> getMoveListToValidateQuery(Period period);
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.service.move.MoveValidateService;
|
||||||
|
import com.axelor.apps.base.db.Period;
|
||||||
|
import com.axelor.apps.base.db.repo.PeriodRepository;
|
||||||
|
import com.axelor.apps.base.db.repo.YearRepository;
|
||||||
|
import com.axelor.apps.base.service.AdjustHistoryService;
|
||||||
|
import com.axelor.apps.base.service.PeriodServiceImpl;
|
||||||
|
import com.axelor.db.Query;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class PeriodServiceAccountImpl extends PeriodServiceImpl implements PeriodServiceAccount {
|
||||||
|
|
||||||
|
protected MoveValidateService moveValidateService;
|
||||||
|
protected MoveRepository moveRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PeriodServiceAccountImpl(
|
||||||
|
PeriodRepository periodRepo,
|
||||||
|
AdjustHistoryService adjustHistoryService,
|
||||||
|
MoveValidateService moveValidateService,
|
||||||
|
MoveRepository moveRepository) {
|
||||||
|
super(periodRepo, adjustHistoryService);
|
||||||
|
this.moveValidateService = moveValidateService;
|
||||||
|
this.moveRepository = moveRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close(Period period) throws AxelorException {
|
||||||
|
|
||||||
|
if (period.getYear().getTypeSelect() == YearRepository.TYPE_FISCAL) {
|
||||||
|
moveValidateService.validateMultiple(getMoveListToValidateQuery(period));
|
||||||
|
period = periodRepo.find(period.getId());
|
||||||
|
}
|
||||||
|
super.close(period);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query<Move> getMoveListToValidateQuery(Period period) {
|
||||||
|
return moveRepository
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.period.id = ?1 AND (self.statusSelect NOT IN (?2,?3, ?4) OR (self.statusSelect = ?2 AND (self.archived = false OR self.archived is null)))",
|
||||||
|
period.getId(),
|
||||||
|
MoveRepository.STATUS_NEW,
|
||||||
|
MoveRepository.STATUS_VALIDATED,
|
||||||
|
MoveRepository.STATUS_CANCELED)
|
||||||
|
.order("date")
|
||||||
|
.order("id");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.ReconcileGroup;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
|
||||||
|
public interface ReconcileGroupSequenceService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sequence for reconcile group, based on the status of the reconcile group, the sequence can
|
||||||
|
* be draft or final.
|
||||||
|
*/
|
||||||
|
void fillCodeFromSequence(ReconcileGroup reconcileGroup) throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.ReconcileGroup;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileGroupRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
|
||||||
|
public class ReconcileGroupSequenceServiceImpl implements ReconcileGroupSequenceService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillCodeFromSequence(ReconcileGroup reconcileGroup) throws AxelorException {
|
||||||
|
String sequenceCode;
|
||||||
|
String exceptionMessage;
|
||||||
|
if (reconcileGroup.getStatusSelect() == ReconcileGroupRepository.STATUS_FINAL) {
|
||||||
|
sequenceCode = SequenceRepository.RECONCILE_GROUP_FINAL;
|
||||||
|
exceptionMessage = IExceptionMessage.RECONCILE_GROUP_NO_FINAL_SEQUENCE;
|
||||||
|
} else {
|
||||||
|
sequenceCode = SequenceRepository.RECONCILE_GROUP_DRAFT;
|
||||||
|
exceptionMessage = IExceptionMessage.RECONCILE_GROUP_NO_TEMP_SEQUENCE;
|
||||||
|
}
|
||||||
|
String code =
|
||||||
|
Beans.get(SequenceService.class)
|
||||||
|
.getSequenceNumber(sequenceCode, reconcileGroup.getCompany());
|
||||||
|
|
||||||
|
if (code == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(exceptionMessage),
|
||||||
|
reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
reconcileGroup.setCode(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.account.db.ReconcileGroup;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface ReconcileGroupService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the given reconcile group. A reconcile Group can be validated if it is not empty and
|
||||||
|
* its lines are balanced.
|
||||||
|
*
|
||||||
|
* @param reconcileGroup a reconcile group.
|
||||||
|
* @param reconcileList a list of reconcile.
|
||||||
|
* @throws AxelorException if the reconcile list is empty.
|
||||||
|
*/
|
||||||
|
void validate(ReconcileGroup reconcileGroup, List<Reconcile> reconcileList)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given reconcile lines are balanced.
|
||||||
|
*
|
||||||
|
* @param reconcileList a list of reconcile.
|
||||||
|
*/
|
||||||
|
boolean isBalanced(List<Reconcile> reconcileList) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link ReconcileGroupService#findOrMergeGroup} to get a reconcile group. If not found,
|
||||||
|
* create one with {@link ReconcileGroupService#createReconcileGroup}
|
||||||
|
*
|
||||||
|
* @param reconcile a confirmed reconcile
|
||||||
|
* @return the created or found group.
|
||||||
|
*/
|
||||||
|
ReconcileGroup findOrCreateGroup(Reconcile reconcile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the corresponding group for a given reconcile. If two or more reconcile group are found,
|
||||||
|
* then return the merge between them.
|
||||||
|
*
|
||||||
|
* @param reconcile a confirmed reconcile.
|
||||||
|
* @return an optional with the reconcile group if it was found. Else an empty optional.
|
||||||
|
*/
|
||||||
|
Optional<ReconcileGroup> findOrMergeGroup(Reconcile reconcile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge reconcile groups into one. The created reconcile group will have a new sequence and all
|
||||||
|
* reconcile lines from the groups.
|
||||||
|
*
|
||||||
|
* @param reconcileGroupList a non empty list of reconcile group to merge.
|
||||||
|
* @return the created reconcile group.
|
||||||
|
*/
|
||||||
|
ReconcileGroup mergeReconcileGroups(List<ReconcileGroup> reconcileGroupList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a reconcile group with the given reconcile.
|
||||||
|
*
|
||||||
|
* @param company a confirmed reconcile.
|
||||||
|
* @return a new reconcile group.
|
||||||
|
*/
|
||||||
|
ReconcileGroup createReconcileGroup(Company company);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a reconcile to a group and validate the group if it is balanced.
|
||||||
|
*
|
||||||
|
* @param reconcileGroup a reconcileGroup.
|
||||||
|
* @param reconcile a reconcile.
|
||||||
|
*/
|
||||||
|
void addAndValidate(ReconcileGroup reconcileGroup, Reconcile reconcile) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a reconcile to a group and validate the group if it is balanced.
|
||||||
|
*
|
||||||
|
* @param reconcileGroup a reconcileGroup.
|
||||||
|
* @param List<reconcile> a list reconcile.
|
||||||
|
*/
|
||||||
|
public void addAllAndValidate(ReconcileGroup reconcileGroup, List<Reconcile> reconcileList)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the reconcile and its move line to the reconcile group.
|
||||||
|
*
|
||||||
|
* @param reconcileGroup a reconcileGroup.
|
||||||
|
* @param reconcile the confirmed reconcile to be added.
|
||||||
|
*/
|
||||||
|
void addToReconcileGroup(ReconcileGroup reconcileGroup, Reconcile reconcile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a reconcile from a reconcile group then update the group.
|
||||||
|
*
|
||||||
|
* @param reconcile a reconcile with a reconcile group.
|
||||||
|
*/
|
||||||
|
void remove(Reconcile reconcile) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the status and the sequence of a reconcile group.
|
||||||
|
*
|
||||||
|
* @param reconcileGroup
|
||||||
|
*/
|
||||||
|
void updateStatus(ReconcileGroup reconcileGroup) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unletter every moveline and update unlettering date.
|
||||||
|
*
|
||||||
|
* @param reconcileGroup
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
void unletter(ReconcileGroup reconcileGroup) throws AxelorException;
|
||||||
|
}
|
||||||
@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.account.db.ReconcileGroup;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileGroupRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
|
public class ReconcileGroupServiceImpl implements ReconcileGroupService {
|
||||||
|
|
||||||
|
protected ReconcileGroupRepository reconcileGroupRepository;
|
||||||
|
protected ReconcileRepository reconcileRepository;
|
||||||
|
protected MoveLineRepository moveLineRepository;
|
||||||
|
protected ReconcileService reconcileService;
|
||||||
|
protected AppBaseService appBaseService;
|
||||||
|
protected ReconcileGroupSequenceService reconcileGroupSequenceService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ReconcileGroupServiceImpl(
|
||||||
|
ReconcileGroupRepository reconcileGroupRepository,
|
||||||
|
ReconcileRepository reconcileRepository,
|
||||||
|
MoveLineRepository moveLineRepository,
|
||||||
|
ReconcileService reconcileService,
|
||||||
|
AppBaseService appBaseService,
|
||||||
|
ReconcileGroupSequenceService reconcileGroupSequenceService) {
|
||||||
|
this.reconcileGroupRepository = reconcileGroupRepository;
|
||||||
|
this.reconcileRepository = reconcileRepository;
|
||||||
|
this.moveLineRepository = moveLineRepository;
|
||||||
|
this.reconcileService = reconcileService;
|
||||||
|
this.appBaseService = appBaseService;
|
||||||
|
this.reconcileGroupSequenceService = reconcileGroupSequenceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void validate(ReconcileGroup reconcileGroup, List<Reconcile> reconcileList)
|
||||||
|
throws AxelorException {
|
||||||
|
if (CollectionUtils.isEmpty(reconcileList)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_GROUP_VALIDATION_NO_LINES),
|
||||||
|
reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
reconcileGroup.setStatusSelect(ReconcileGroupRepository.STATUS_FINAL);
|
||||||
|
reconcileGroup.setDateOfLettering(appBaseService.getTodayDate());
|
||||||
|
|
||||||
|
reconcileGroupSequenceService.fillCodeFromSequence(reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBalanced(List<Reconcile> reconcileList) {
|
||||||
|
List<MoveLine> debitMoveLineList =
|
||||||
|
reconcileList
|
||||||
|
.stream()
|
||||||
|
.map(Reconcile::getDebitMoveLine)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<MoveLine> creditMoveLineList =
|
||||||
|
reconcileList
|
||||||
|
.stream()
|
||||||
|
.map(Reconcile::getCreditMoveLine)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<Account> accountList =
|
||||||
|
debitMoveLineList
|
||||||
|
.stream()
|
||||||
|
.map(MoveLine::getAccount)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
accountList.addAll(
|
||||||
|
creditMoveLineList
|
||||||
|
.stream()
|
||||||
|
.map(MoveLine::getAccount)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
|
for (Account account : accountList) {
|
||||||
|
BigDecimal totalDebit =
|
||||||
|
debitMoveLineList
|
||||||
|
.stream()
|
||||||
|
.filter(moveLine -> moveLine.getAccount().equals(account))
|
||||||
|
.map(MoveLine::getDebit)
|
||||||
|
.reduce(BigDecimal::add)
|
||||||
|
.orElse(BigDecimal.ZERO);
|
||||||
|
BigDecimal totalCredit =
|
||||||
|
creditMoveLineList
|
||||||
|
.stream()
|
||||||
|
.filter(moveLine -> moveLine.getAccount().equals(account))
|
||||||
|
.map(MoveLine::getCredit)
|
||||||
|
.reduce(BigDecimal::add)
|
||||||
|
.orElse(BigDecimal.ZERO);
|
||||||
|
if (totalDebit.compareTo(totalCredit) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReconcileGroup findOrCreateGroup(Reconcile reconcile) {
|
||||||
|
return findOrMergeGroup(reconcile)
|
||||||
|
.orElseGet(() -> createReconcileGroup(reconcile.getCompany()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<ReconcileGroup> findOrMergeGroup(Reconcile reconcile) {
|
||||||
|
List<ReconcileGroup> otherReconcileGroupList;
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
MoveLine creditMoveLine = reconcile.getCreditMoveLine();
|
||||||
|
otherReconcileGroupList = new ArrayList<>();
|
||||||
|
if (debitMoveLine.getReconcileGroup() != null) {
|
||||||
|
otherReconcileGroupList.add(debitMoveLine.getReconcileGroup());
|
||||||
|
}
|
||||||
|
if (creditMoveLine.getReconcileGroup() != null) {
|
||||||
|
otherReconcileGroupList.add(creditMoveLine.getReconcileGroup());
|
||||||
|
}
|
||||||
|
otherReconcileGroupList =
|
||||||
|
otherReconcileGroupList.stream().distinct().collect(Collectors.toList());
|
||||||
|
if (otherReconcileGroupList.isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
|
} else if (otherReconcileGroupList.size() == 1) {
|
||||||
|
return Optional.of(otherReconcileGroupList.get(0));
|
||||||
|
} else {
|
||||||
|
return Optional.of(mergeReconcileGroups(otherReconcileGroupList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public ReconcileGroup mergeReconcileGroups(List<ReconcileGroup> reconcileGroupList) {
|
||||||
|
Company company = reconcileGroupList.get(0).getCompany();
|
||||||
|
ReconcileGroup reconcileGroup = createReconcileGroup(company);
|
||||||
|
|
||||||
|
List<Reconcile> reconcileList =
|
||||||
|
reconcileRepository
|
||||||
|
.all()
|
||||||
|
.filter("self.reconcileGroup.id IN (:reconcileGroupIds)")
|
||||||
|
.bind(
|
||||||
|
"reconcileGroupIds",
|
||||||
|
reconcileGroupList.stream().map(ReconcileGroup::getId).collect(Collectors.toList()))
|
||||||
|
.fetch();
|
||||||
|
reconcileList.forEach(reconcile -> addToReconcileGroup(reconcileGroup, reconcile));
|
||||||
|
|
||||||
|
for (ReconcileGroup toDeleteReconcileGroup : reconcileGroupList) {
|
||||||
|
reconcileGroupRepository.remove(toDeleteReconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reconcileGroupRepository.save(reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public ReconcileGroup createReconcileGroup(Company company) {
|
||||||
|
ReconcileGroup reconcileGroup = new ReconcileGroup();
|
||||||
|
reconcileGroup.setCompany(company);
|
||||||
|
return reconcileGroupRepository.save(reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAndValidate(ReconcileGroup reconcileGroup, Reconcile reconcile)
|
||||||
|
throws AxelorException {
|
||||||
|
List<Reconcile> reconcileList = this.getReconcileList(reconcileGroup);
|
||||||
|
reconcileList.add(reconcile);
|
||||||
|
addToReconcileGroup(reconcileGroup, reconcile);
|
||||||
|
if (isBalanced(reconcileList)) {
|
||||||
|
validate(reconcileGroup, reconcileList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAllAndValidate(ReconcileGroup reconcileGroup, List<Reconcile> reconcileList)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
for (Reconcile reconcile : reconcileList) {
|
||||||
|
addToReconcileGroup(reconcileGroup, reconcile);
|
||||||
|
}
|
||||||
|
if (isBalanced(reconcileList)) {
|
||||||
|
validate(reconcileGroup, reconcileList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToReconcileGroup(ReconcileGroup reconcileGroup, Reconcile reconcile) {
|
||||||
|
reconcile.setReconcileGroup(reconcileGroup);
|
||||||
|
reconcile.getDebitMoveLine().setReconcileGroup(reconcileGroup);
|
||||||
|
reconcile.getCreditMoveLine().setReconcileGroup(reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
ReconcileGroup reconcileGroup = reconcile.getReconcileGroup();
|
||||||
|
|
||||||
|
// update move lines
|
||||||
|
List<MoveLine> moveLineToRemoveList =
|
||||||
|
moveLineRepository.findByReconcileGroup(reconcileGroup).fetch();
|
||||||
|
moveLineToRemoveList.forEach(moveLine -> moveLine.setReconcileGroup(null));
|
||||||
|
|
||||||
|
List<Reconcile> reconcileList = this.getReconcileList(reconcileGroup);
|
||||||
|
reconcileList
|
||||||
|
.stream()
|
||||||
|
.map(Reconcile::getDebitMoveLine)
|
||||||
|
.forEach(moveLine -> moveLine.setReconcileGroup(reconcileGroup));
|
||||||
|
reconcileList
|
||||||
|
.stream()
|
||||||
|
.map(Reconcile::getCreditMoveLine)
|
||||||
|
.forEach(moveLine -> moveLine.setReconcileGroup(reconcileGroup));
|
||||||
|
|
||||||
|
// update status
|
||||||
|
updateStatus(reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStatus(ReconcileGroup reconcileGroup) throws AxelorException {
|
||||||
|
List<Reconcile> reconcileList = this.getReconcileList(reconcileGroup);
|
||||||
|
int status = reconcileGroup.getStatusSelect();
|
||||||
|
if (CollectionUtils.isNotEmpty(reconcileList)
|
||||||
|
&& isBalanced(reconcileList)
|
||||||
|
&& status == ReconcileGroupRepository.STATUS_TEMPORARY) {
|
||||||
|
validate(reconcileGroup, reconcileList);
|
||||||
|
} else if (status == ReconcileGroupRepository.STATUS_FINAL) {
|
||||||
|
// it is not balanced or the collection is empty.
|
||||||
|
if (CollectionUtils.isEmpty(reconcileList)) {
|
||||||
|
reconcileGroup.setStatusSelect(ReconcileGroupRepository.STATUS_UNLETTERED);
|
||||||
|
reconcileGroup.setUnletteringDate(appBaseService.getTodayDate());
|
||||||
|
reconcileGroupRepository.save(reconcileGroup);
|
||||||
|
} else {
|
||||||
|
reconcileGroup.setStatusSelect(ReconcileGroupRepository.STATUS_TEMPORARY);
|
||||||
|
reconcileGroupSequenceService.fillCodeFromSequence(reconcileGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void unletter(ReconcileGroup reconcileGroup) throws AxelorException {
|
||||||
|
List<Reconcile> reconcileList = this.getReconcileList(reconcileGroup);
|
||||||
|
|
||||||
|
for (Reconcile reconcile : reconcileList) {
|
||||||
|
reconcileService.unreconcile(reconcile);
|
||||||
|
}
|
||||||
|
|
||||||
|
reconcileGroup.setUnletteringDate(appBaseService.getTodayDate());
|
||||||
|
reconcileGroup.setStatusSelect(ReconcileGroupRepository.STATUS_UNLETTERED);
|
||||||
|
reconcileGroupRepository.save(reconcileGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Reconcile> getReconcileList(ReconcileGroup reconcileGroup) {
|
||||||
|
return reconcileRepository
|
||||||
|
.all()
|
||||||
|
.filter("self.reconcileGroup.id = :reconcileGroupId AND self.statusSelect = :confirmed")
|
||||||
|
.bind("reconcileGroupId", reconcileGroup.getId())
|
||||||
|
.bind("confirmed", ReconcileRepository.STATUS_CONFIRMED)
|
||||||
|
.fetch();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
public class ReconcileSequenceService {
|
||||||
|
|
||||||
|
protected SequenceService sequenceService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ReconcileSequenceService(SequenceService sequenceService) {
|
||||||
|
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSequence(Reconcile reconcile) throws AxelorException {
|
||||||
|
reconcile.setReconcileSeq(this.getSequence(reconcile));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getSequence(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
SequenceService sequenceService = Beans.get(SequenceService.class);
|
||||||
|
String seq =
|
||||||
|
sequenceService.getSequenceNumber(
|
||||||
|
SequenceRepository.RECONCILE, reconcile.getDebitMoveLine().getMove().getCompany());
|
||||||
|
if (seq == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_6),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
reconcile.getCompany().getName());
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDraftSequence(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
if (reconcile.getId() != null
|
||||||
|
&& Strings.isNullOrEmpty(reconcile.getReconcileSeq())
|
||||||
|
&& reconcile.getStatusSelect() == ReconcileRepository.STATUS_DRAFT) {
|
||||||
|
reconcile.setReconcileSeq(sequenceService.getDraftSequenceNumber(reconcile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ReconcileService {
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Reconcile createReconcile(
|
||||||
|
MoveLine debitMoveLine,
|
||||||
|
MoveLine creditMoveLine,
|
||||||
|
BigDecimal amount,
|
||||||
|
boolean canBeZeroBalanceOk);
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public Reconcile confirmReconcile(Reconcile reconcile, boolean updateInvoicePayments)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public Reconcile confirmPaymentVoucherReconcile(
|
||||||
|
Reconcile reconcile, boolean updateInvoicePayments) throws AxelorException;
|
||||||
|
|
||||||
|
public void reconcilePreconditions(Reconcile reconcile) throws AxelorException;
|
||||||
|
|
||||||
|
public void updatePartnerAccountingSituation(Reconcile reconcile) throws AxelorException;
|
||||||
|
|
||||||
|
public List<Partner> getPartners(Reconcile reconcile);
|
||||||
|
|
||||||
|
public Reconcile reconcile(
|
||||||
|
MoveLine debitMoveLine,
|
||||||
|
MoveLine creditMoveLine,
|
||||||
|
boolean canBeZeroBalanceOk,
|
||||||
|
boolean updateInvoicePayments)
|
||||||
|
throws AxelorException;
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void unreconcile(Reconcile reconcile) throws AxelorException;
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void canBeZeroBalance(Reconcile reconcile) throws AxelorException;
|
||||||
|
|
||||||
|
public void balanceCredit(MoveLine creditMoveLine) throws AxelorException;
|
||||||
|
|
||||||
|
public List<Reconcile> getReconciles(MoveLine moveLine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a reconcile to an existing or created reconcile group.
|
||||||
|
*
|
||||||
|
* @param reconcile a confirmed reconcile.
|
||||||
|
*/
|
||||||
|
void addToReconcileGroup(Reconcile reconcile) throws AxelorException;
|
||||||
|
|
||||||
|
public static boolean isReconcilable(MoveLine acc1, MoveLine acc2) {
|
||||||
|
return acc1.getAccount().getReconcileOk()
|
||||||
|
&& acc2.getAccount().getReconcileOk()
|
||||||
|
&& (acc1.getAccount().equals(acc2.getAccount())
|
||||||
|
|| acc1.getAccount().getCompatibleAccountSet().contains(acc2.getAccount()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,620 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.InvoicePayment;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.account.db.ReconcileGroup;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoicePaymentRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReconcileRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveAdjustementService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveLineService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveToolService;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentCancelService;
|
||||||
|
import com.axelor.apps.account.service.payment.invoice.payment.InvoicePaymentCreateService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ReconcileServiceImpl implements ReconcileService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected MoveToolService moveToolService;
|
||||||
|
protected AccountCustomerService accountCustomerService;
|
||||||
|
protected AccountConfigService accountConfigService;
|
||||||
|
protected ReconcileRepository reconcileRepository;
|
||||||
|
protected MoveAdjustementService moveAdjustementService;
|
||||||
|
protected ReconcileSequenceService reconcileSequenceService;
|
||||||
|
protected InvoicePaymentCreateService invoicePaymentCreateService;
|
||||||
|
protected InvoicePaymentCancelService invoicePaymentCancelService;
|
||||||
|
protected MoveLineService moveLineService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ReconcileServiceImpl(
|
||||||
|
MoveToolService moveToolService,
|
||||||
|
AccountCustomerService accountCustomerService,
|
||||||
|
AccountConfigService accountConfigService,
|
||||||
|
ReconcileRepository reconcileRepository,
|
||||||
|
MoveAdjustementService moveAdjustementService,
|
||||||
|
ReconcileSequenceService reconcileSequenceService,
|
||||||
|
InvoicePaymentCancelService invoicePaymentCancelService,
|
||||||
|
InvoicePaymentCreateService invoicePaymentCreateService,
|
||||||
|
MoveLineService moveLineService) {
|
||||||
|
|
||||||
|
this.moveToolService = moveToolService;
|
||||||
|
this.accountCustomerService = accountCustomerService;
|
||||||
|
this.accountConfigService = accountConfigService;
|
||||||
|
this.reconcileRepository = reconcileRepository;
|
||||||
|
this.moveAdjustementService = moveAdjustementService;
|
||||||
|
this.reconcileSequenceService = reconcileSequenceService;
|
||||||
|
this.invoicePaymentCancelService = invoicePaymentCancelService;
|
||||||
|
this.invoicePaymentCreateService = invoicePaymentCreateService;
|
||||||
|
this.moveLineService = moveLineService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de créer une réconciliation en passant les paramètres qu'il faut
|
||||||
|
*
|
||||||
|
* @param lineDebit Une ligne d'écriture au débit
|
||||||
|
* @param lineCredit Une ligne d'écriture au crédit
|
||||||
|
* @param amount Le montant à reconciler
|
||||||
|
* @param canBeZeroBalanceOk Peut être soldé?
|
||||||
|
* @return Une reconciliation
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Reconcile createReconcile(
|
||||||
|
MoveLine debitMoveLine,
|
||||||
|
MoveLine creditMoveLine,
|
||||||
|
BigDecimal amount,
|
||||||
|
boolean canBeZeroBalanceOk) {
|
||||||
|
|
||||||
|
if (ReconcileService.isReconcilable(debitMoveLine, creditMoveLine)
|
||||||
|
&& amount.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
log.debug(
|
||||||
|
"Create Reconcile (Company : {}, Debit MoveLine : {}, Credit MoveLine : {}, Amount : {}, Can be zero balance ? {} )",
|
||||||
|
debitMoveLine.getMove().getCompany(),
|
||||||
|
debitMoveLine.getName(),
|
||||||
|
creditMoveLine.getName(),
|
||||||
|
amount,
|
||||||
|
canBeZeroBalanceOk);
|
||||||
|
|
||||||
|
Reconcile reconcile =
|
||||||
|
new Reconcile(
|
||||||
|
debitMoveLine.getMove().getCompany(),
|
||||||
|
amount.setScale(2, RoundingMode.HALF_EVEN),
|
||||||
|
debitMoveLine,
|
||||||
|
creditMoveLine,
|
||||||
|
ReconcileRepository.STATUS_DRAFT,
|
||||||
|
canBeZeroBalanceOk);
|
||||||
|
|
||||||
|
if (!moveToolService.isDebitMoveLine(debitMoveLine)) {
|
||||||
|
|
||||||
|
reconcile.setDebitMoveLine(creditMoveLine);
|
||||||
|
reconcile.setCreditMoveLine(debitMoveLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reconcileRepository.save(reconcile);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de confirmer une réconciliation On ne peut réconcilier que des moveLine ayant le même
|
||||||
|
* compte
|
||||||
|
*
|
||||||
|
* @param reconcile Une reconciliation
|
||||||
|
* @return L'etat de la reconciliation
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public Reconcile confirmReconcile(Reconcile reconcile, boolean updateInvoicePayments)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
this.reconcilePreconditions(reconcile);
|
||||||
|
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
MoveLine creditMoveLine = reconcile.getCreditMoveLine();
|
||||||
|
|
||||||
|
// Add the reconciled amount to the reconciled amount in the move line
|
||||||
|
creditMoveLine.setAmountPaid(creditMoveLine.getAmountPaid().add(reconcile.getAmount()));
|
||||||
|
debitMoveLine.setAmountPaid(debitMoveLine.getAmountPaid().add(reconcile.getAmount()));
|
||||||
|
|
||||||
|
reconcile = reconcileRepository.save(reconcile);
|
||||||
|
|
||||||
|
reconcile.setStatusSelect(ReconcileRepository.STATUS_CONFIRMED);
|
||||||
|
|
||||||
|
if (reconcile.getCanBeZeroBalanceOk()) {
|
||||||
|
// Alors nous utilisons la règle de gestion consitant à imputer l'écart sur un compte
|
||||||
|
// transitoire si le seuil est respecté
|
||||||
|
canBeZeroBalance(reconcile);
|
||||||
|
}
|
||||||
|
|
||||||
|
reconcile.setReconciliationDate(LocalDate.now());
|
||||||
|
|
||||||
|
reconcileSequenceService.setSequence(reconcile);
|
||||||
|
|
||||||
|
this.updatePartnerAccountingSituation(reconcile);
|
||||||
|
this.updateInvoiceCompanyInTaxTotalRemaining(reconcile);
|
||||||
|
this.udpatePaymentTax(reconcile);
|
||||||
|
if (updateInvoicePayments) {
|
||||||
|
this.updateInvoicePayments(reconcile);
|
||||||
|
}
|
||||||
|
// this.addToReconcileGroup(reconcile);
|
||||||
|
|
||||||
|
return reconcileRepository.save(reconcile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAllToReconcileGroup(List<Reconcile> reconciles) throws AxelorException {
|
||||||
|
ReconcileGroupService reconcileGroupService = Beans.get(ReconcileGroupService.class);
|
||||||
|
|
||||||
|
ReconcileGroup reconcileGroup = reconcileGroupService.findOrCreateGroup(reconciles.get(0));
|
||||||
|
reconcileGroupService.addAllAndValidate(reconcileGroup, reconciles);
|
||||||
|
for (Reconcile reconcile : reconciles) {
|
||||||
|
this.confirmReconcile(reconcile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToReconcileGroup(Reconcile reconcile) throws AxelorException {
|
||||||
|
ReconcileGroupService reconcileGroupService = Beans.get(ReconcileGroupService.class);
|
||||||
|
|
||||||
|
ReconcileGroup reconcileGroup = reconcileGroupService.findOrCreateGroup(reconcile);
|
||||||
|
|
||||||
|
reconcileGroupService.addAndValidate(reconcileGroup, reconcile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconcilePreconditions(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
MoveLine creditMoveLine = reconcile.getCreditMoveLine();
|
||||||
|
|
||||||
|
if (debitMoveLine == null || creditMoveLine == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_1),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if move lines companies are the same as the reconcile company
|
||||||
|
Company reconcileCompany = reconcile.getCompany();
|
||||||
|
Company debitMoveLineCompany = debitMoveLine.getMove().getCompany();
|
||||||
|
Company creditMoveLineCompany = creditMoveLine.getMove().getCompany();
|
||||||
|
if (!debitMoveLineCompany.equals(reconcileCompany)
|
||||||
|
&& !creditMoveLineCompany.equals(reconcileCompany)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
String.format(
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_7),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
debitMoveLineCompany,
|
||||||
|
creditMoveLineCompany,
|
||||||
|
reconcileCompany),
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if move lines accounts are the same (debit and credit)
|
||||||
|
if (!creditMoveLine.getAccount().equals(debitMoveLine.getAccount())) {
|
||||||
|
log.debug(
|
||||||
|
"Compte ligne de credit : {} , Compte ligne de debit : {}",
|
||||||
|
creditMoveLine.getAccount(),
|
||||||
|
debitMoveLine.getAccount());
|
||||||
|
|
||||||
|
// Check if move lines accounts are compatible
|
||||||
|
if (!debitMoveLine
|
||||||
|
.getAccount()
|
||||||
|
.getCompatibleAccountSet()
|
||||||
|
.contains(creditMoveLine.getAccount())) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_2),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the amount to reconcile is != zero
|
||||||
|
if (reconcile.getAmount() == null || reconcile.getAmount().compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_4),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
reconcile.getReconcileSeq(),
|
||||||
|
debitMoveLine.getName(),
|
||||||
|
debitMoveLine.getAccount().getLabel(),
|
||||||
|
creditMoveLine.getName(),
|
||||||
|
creditMoveLine.getAccount().getLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((reconcile
|
||||||
|
.getAmount()
|
||||||
|
.compareTo(creditMoveLine.getCredit().subtract(creditMoveLine.getAmountPaid()))
|
||||||
|
> 0
|
||||||
|
|| (reconcile
|
||||||
|
.getAmount()
|
||||||
|
.compareTo(debitMoveLine.getDebit().subtract(debitMoveLine.getAmountPaid()))
|
||||||
|
> 0))) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.RECONCILE_5) + " " + I18n.get(IExceptionMessage.RECONCILE_3),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
reconcile.getReconcileSeq(),
|
||||||
|
reconcile.getAmount(),
|
||||||
|
debitMoveLine.getName(),
|
||||||
|
debitMoveLine.getAccount().getLabel(),
|
||||||
|
debitMoveLine.getDebit().subtract(debitMoveLine.getAmountPaid()),
|
||||||
|
creditMoveLine.getName(),
|
||||||
|
creditMoveLine.getAccount().getLabel(),
|
||||||
|
creditMoveLine.getCredit().subtract(creditMoveLine.getAmountPaid()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePartnerAccountingSituation(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
List<Partner> partnerList = this.getPartners(reconcile);
|
||||||
|
|
||||||
|
if (partnerList != null && !partnerList.isEmpty()) {
|
||||||
|
|
||||||
|
Company company = reconcile.getDebitMoveLine().getMove().getCompany();
|
||||||
|
|
||||||
|
if (AccountingService.getUpdateCustomerAccount()) {
|
||||||
|
accountCustomerService.updatePartnerAccountingSituation(
|
||||||
|
partnerList, company, true, true, false);
|
||||||
|
} else {
|
||||||
|
accountCustomerService.flagPartners(partnerList, company);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Partner> getPartners(Reconcile reconcile) {
|
||||||
|
|
||||||
|
List<Partner> partnerList = Lists.newArrayList();
|
||||||
|
Partner debitPartner = reconcile.getDebitMoveLine().getPartner();
|
||||||
|
Partner creditPartner = reconcile.getCreditMoveLine().getPartner();
|
||||||
|
if (debitPartner != null && creditPartner != null && debitPartner.equals(creditPartner)) {
|
||||||
|
partnerList.add(debitPartner);
|
||||||
|
} else if (debitPartner != null) {
|
||||||
|
partnerList.add(debitPartner);
|
||||||
|
} else if (creditPartner != null) {
|
||||||
|
partnerList.add(creditPartner);
|
||||||
|
}
|
||||||
|
|
||||||
|
return partnerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateInvoiceCompanyInTaxTotalRemaining(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
Invoice debitInvoice = reconcile.getDebitMoveLine().getMove().getInvoice();
|
||||||
|
Invoice creditInvoice = reconcile.getCreditMoveLine().getMove().getInvoice();
|
||||||
|
|
||||||
|
// Update amount remaining on invoice or refund
|
||||||
|
if (debitInvoice != null) {
|
||||||
|
|
||||||
|
debitInvoice.setCompanyInTaxTotalRemaining(
|
||||||
|
moveToolService.getInTaxTotalRemaining(debitInvoice));
|
||||||
|
}
|
||||||
|
if (creditInvoice != null) {
|
||||||
|
|
||||||
|
creditInvoice.setCompanyInTaxTotalRemaining(
|
||||||
|
moveToolService.getInTaxTotalRemaining(creditInvoice));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateInvoicePayments(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
MoveLine creditMoveLine = reconcile.getCreditMoveLine();
|
||||||
|
Move debitMove = debitMoveLine.getMove();
|
||||||
|
Move creditMove = creditMoveLine.getMove();
|
||||||
|
Invoice debitInvoice = debitMove.getInvoice();
|
||||||
|
Invoice creditInvoice = creditMove.getInvoice();
|
||||||
|
BigDecimal amount = reconcile.getAmount();
|
||||||
|
|
||||||
|
if (debitInvoice != null
|
||||||
|
&& debitMoveLine.getAccount().getUseForPartnerBalance()
|
||||||
|
&& creditMoveLine.getAccount().getUseForPartnerBalance()) {
|
||||||
|
InvoicePayment debitInvoicePayment =
|
||||||
|
invoicePaymentCreateService.createInvoicePayment(debitInvoice, amount, creditMove);
|
||||||
|
debitInvoicePayment.setReconcile(reconcile);
|
||||||
|
}
|
||||||
|
if (creditInvoice != null
|
||||||
|
&& debitMoveLine.getAccount().getUseForPartnerBalance()
|
||||||
|
&& creditMoveLine.getAccount().getUseForPartnerBalance()) {
|
||||||
|
InvoicePayment creditInvoicePayment =
|
||||||
|
invoicePaymentCreateService.createInvoicePayment(creditInvoice, amount, debitMove);
|
||||||
|
creditInvoicePayment.setReconcile(reconcile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void udpatePaymentTax(Reconcile reconcile) throws AxelorException {
|
||||||
|
Move debitMove = reconcile.getDebitMoveLine().getMove();
|
||||||
|
Move creditMove = reconcile.getCreditMoveLine().getMove();
|
||||||
|
Invoice debitInvoice = debitMove.getInvoice();
|
||||||
|
Invoice creditInvoice = creditMove.getInvoice();
|
||||||
|
|
||||||
|
if (debitInvoice != null && creditInvoice == null) {
|
||||||
|
moveLineService.generateTaxPaymentMoveLineList(
|
||||||
|
reconcile.getCreditMoveLine(), debitInvoice, reconcile);
|
||||||
|
}
|
||||||
|
if (creditInvoice != null && debitInvoice == null) {
|
||||||
|
moveLineService.generateTaxPaymentMoveLineList(
|
||||||
|
reconcile.getDebitMoveLine(), creditInvoice, reconcile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de lettrer une écriture au débit avec une écriture au crédit
|
||||||
|
*
|
||||||
|
* @param debitMoveLine
|
||||||
|
* @param creditMoveLine
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public Reconcile reconcile(
|
||||||
|
MoveLine debitMoveLine,
|
||||||
|
MoveLine creditMoveLine,
|
||||||
|
boolean canBeZeroBalanceOk,
|
||||||
|
boolean updateInvoicePayments)
|
||||||
|
throws AxelorException {
|
||||||
|
BigDecimal amount = debitMoveLine.getAmountRemaining().min(creditMoveLine.getAmountRemaining());
|
||||||
|
Reconcile reconcile =
|
||||||
|
this.createReconcile(debitMoveLine, creditMoveLine, amount, canBeZeroBalanceOk);
|
||||||
|
if (reconcile != null) {
|
||||||
|
this.confirmReconcile(reconcile, updateInvoicePayments);
|
||||||
|
return reconcile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de déréconcilier
|
||||||
|
*
|
||||||
|
* @param reconcile Une reconciliation
|
||||||
|
* @return L'etat de la réconciliation
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void unreconcile(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
log.debug("unreconcile : reconcile : {}", reconcile);
|
||||||
|
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
MoveLine creditMoveLine = reconcile.getCreditMoveLine();
|
||||||
|
|
||||||
|
// Change the state
|
||||||
|
reconcile.setStatusSelect(ReconcileRepository.STATUS_CANCELED);
|
||||||
|
// Add the reconciled amount to the reconciled amount in the move line
|
||||||
|
creditMoveLine.setAmountPaid(creditMoveLine.getAmountPaid().subtract(reconcile.getAmount()));
|
||||||
|
debitMoveLine.setAmountPaid(debitMoveLine.getAmountPaid().subtract(reconcile.getAmount()));
|
||||||
|
|
||||||
|
reconcileRepository.save(reconcile);
|
||||||
|
|
||||||
|
// Update amount remaining on invoice or refund
|
||||||
|
this.updatePartnerAccountingSituation(reconcile);
|
||||||
|
this.updateInvoiceCompanyInTaxTotalRemaining(reconcile);
|
||||||
|
this.updateInvoicePaymentsCanceled(reconcile);
|
||||||
|
this.reverseTaxPaymentMoveLines(reconcile);
|
||||||
|
// Update reconcile group
|
||||||
|
Beans.get(ReconcileGroupService.class).remove(reconcile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void unreconcile2(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
log.debug("unreconcile : reconcile : {}", reconcile);
|
||||||
|
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
MoveLine creditMoveLine = reconcile.getCreditMoveLine();
|
||||||
|
|
||||||
|
// Change the state
|
||||||
|
reconcile.setStatusSelect(ReconcileRepository.STATUS_CANCELED);
|
||||||
|
// Add the reconciled amount to the reconciled amount in the move line
|
||||||
|
creditMoveLine.setAmountPaid(creditMoveLine.getAmountPaid().subtract(reconcile.getAmount()));
|
||||||
|
debitMoveLine.setAmountPaid(debitMoveLine.getAmountPaid().subtract(reconcile.getAmount()));
|
||||||
|
reconcileRepository.save(reconcile);
|
||||||
|
|
||||||
|
// Update amount remaining on invoice or refund
|
||||||
|
this.updatePartnerAccountingSituation(reconcile);
|
||||||
|
this.updateInvoiceCompanyInTaxTotalRemaining(reconcile);
|
||||||
|
this.updateInvoicePaymentsCanceled(reconcile);
|
||||||
|
this.reverseTaxPaymentMoveLines(reconcile);
|
||||||
|
// Update reconcile group
|
||||||
|
// Beans.get(ReconcileGroupService.class).remove(reconcile);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reverseTaxPaymentMoveLines(Reconcile reconcile) throws AxelorException {
|
||||||
|
Move debitMove = reconcile.getDebitMoveLine().getMove();
|
||||||
|
Move creditMove = reconcile.getCreditMoveLine().getMove();
|
||||||
|
Invoice debitInvoice = debitMove.getInvoice();
|
||||||
|
Invoice creditInvoice = creditMove.getInvoice();
|
||||||
|
if (debitInvoice == null) {
|
||||||
|
moveLineService.reverseTaxPaymentMoveLines(reconcile.getDebitMoveLine(), reconcile);
|
||||||
|
}
|
||||||
|
if (creditInvoice == null) {
|
||||||
|
moveLineService.reverseTaxPaymentMoveLines(reconcile.getCreditMoveLine(), reconcile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateInvoicePaymentsCanceled(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
log.debug("updateInvoicePaymentsCanceled : reconcile : {}", reconcile);
|
||||||
|
|
||||||
|
List<InvoicePayment> invoicePaymentList =
|
||||||
|
Beans.get(InvoicePaymentRepository.class)
|
||||||
|
.all()
|
||||||
|
.filter("self.reconcile = ?1", reconcile)
|
||||||
|
.fetch();
|
||||||
|
|
||||||
|
for (InvoicePayment invoicePayment : invoicePaymentList) {
|
||||||
|
invoicePaymentCancelService.updateCancelStatus(invoicePayment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de gérer les écarts de règlement, check sur la case à cocher 'Peut être
|
||||||
|
* soldé' Alors nous utilisons la règle de gestion consitant à imputer l'écart sur un compte
|
||||||
|
* transitoire si le seuil est respecté
|
||||||
|
*
|
||||||
|
* @param reconcile Une reconciliation
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void canBeZeroBalance(Reconcile reconcile) throws AxelorException {
|
||||||
|
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
|
||||||
|
BigDecimal debitAmountRemaining = debitMoveLine.getAmountRemaining();
|
||||||
|
log.debug("Montant à payer / à lettrer au débit : {}", debitAmountRemaining);
|
||||||
|
if (debitAmountRemaining.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
Company company = reconcile.getDebitMoveLine().getMove().getCompany();
|
||||||
|
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
|
||||||
|
if (debitAmountRemaining.plus().compareTo(accountConfig.getThresholdDistanceFromRegulation())
|
||||||
|
< 0
|
||||||
|
|| reconcile.getMustBeZeroBalanceOk()) {
|
||||||
|
|
||||||
|
log.debug("Seuil respecté");
|
||||||
|
|
||||||
|
log.debug("Entrain de se cree");
|
||||||
|
|
||||||
|
MoveLine creditAdjustMoveLine =
|
||||||
|
moveAdjustementService.createAdjustmentCreditMove(debitMoveLine);
|
||||||
|
|
||||||
|
// Création de la réconciliation
|
||||||
|
Reconcile newReconcile =
|
||||||
|
this.createReconcile(debitMoveLine, creditAdjustMoveLine, debitAmountRemaining, false);
|
||||||
|
if (newReconcile != null) {
|
||||||
|
this.confirmReconcile(newReconcile, true);
|
||||||
|
reconcileRepository.save(newReconcile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reconcile.setCanBeZeroBalanceOk(false);
|
||||||
|
log.debug("Fin de la gestion des écarts de règlement");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solder le trop-perçu si il respect les règles de seuil
|
||||||
|
*
|
||||||
|
* @param creditMoveLine
|
||||||
|
* @param company
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void balanceCredit(MoveLine creditMoveLine) throws AxelorException {
|
||||||
|
if (creditMoveLine != null) {
|
||||||
|
BigDecimal creditAmountRemaining = creditMoveLine.getAmountRemaining();
|
||||||
|
log.debug("Montant à payer / à lettrer au crédit : {}", creditAmountRemaining);
|
||||||
|
log.debug("creditMoveLine: {}", creditMoveLine.toString());
|
||||||
|
|
||||||
|
if (creditAmountRemaining.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
AccountConfig accountConfig =
|
||||||
|
accountConfigService.getAccountConfig(creditMoveLine.getMove().getCompany());
|
||||||
|
|
||||||
|
if (creditAmountRemaining
|
||||||
|
.plus()
|
||||||
|
.compareTo(accountConfig.getThresholdDistanceFromRegulation())
|
||||||
|
< 0) {
|
||||||
|
|
||||||
|
log.debug("Seuil respecté");
|
||||||
|
|
||||||
|
MoveLine debitAdjustmentMoveLine =
|
||||||
|
moveAdjustementService.createAdjustmentDebitMove(creditMoveLine);
|
||||||
|
|
||||||
|
log.debug("/////////////// {}", creditAmountRemaining);
|
||||||
|
// Création de la réconciliation
|
||||||
|
Reconcile newReconcile =
|
||||||
|
this.createReconcile(
|
||||||
|
debitAdjustmentMoveLine, creditMoveLine, creditAmountRemaining, false);
|
||||||
|
if (newReconcile != null) {
|
||||||
|
this.confirmReconcile(newReconcile, true);
|
||||||
|
reconcileRepository.save(newReconcile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Reconcile> getReconciles(MoveLine moveLine) {
|
||||||
|
|
||||||
|
List<Reconcile> debitReconcileList = moveLine.getDebitReconcileList();
|
||||||
|
List<Reconcile> creditReconcileList = moveLine.getCreditReconcileList();
|
||||||
|
|
||||||
|
if (moveToolService.isDebitMoveLine(moveLine)) {
|
||||||
|
return debitReconcileList;
|
||||||
|
} else if (debitReconcileList != null && !creditReconcileList.isEmpty()) {
|
||||||
|
return creditReconcileList;
|
||||||
|
}
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reconcile confirmPaymentVoucherReconcile(
|
||||||
|
Reconcile reconcile, boolean updateInvoicePayments) throws AxelorException {
|
||||||
|
this.reconcilePreconditions(reconcile);
|
||||||
|
|
||||||
|
MoveLine debitMoveLine = reconcile.getDebitMoveLine();
|
||||||
|
MoveLine creditMoveLine = reconcile.getCreditMoveLine();
|
||||||
|
|
||||||
|
// Add the reconciled amount to the reconciled amount in the move line
|
||||||
|
creditMoveLine.setAmountPaid(creditMoveLine.getAmountPaid().add(reconcile.getAmount()));
|
||||||
|
debitMoveLine.setAmountPaid(debitMoveLine.getAmountPaid().add(reconcile.getAmount()));
|
||||||
|
|
||||||
|
reconcile = reconcileRepository.save(reconcile);
|
||||||
|
|
||||||
|
reconcile.setStatusSelect(ReconcileRepository.STATUS_CONFIRMED);
|
||||||
|
|
||||||
|
if (reconcile.getCanBeZeroBalanceOk()) {
|
||||||
|
// Alors nous utilisons la règle de gestion consitant à imputer l'écart sur un compte
|
||||||
|
// transitoire si le seuil est respecté
|
||||||
|
canBeZeroBalance(reconcile);
|
||||||
|
}
|
||||||
|
|
||||||
|
reconcile.setReconciliationDate(LocalDate.now());
|
||||||
|
|
||||||
|
reconcileSequenceService.setSequence(reconcile);
|
||||||
|
|
||||||
|
this.updatePartnerAccountingSituation(reconcile);
|
||||||
|
this.updateInvoiceCompanyInTaxTotalRemaining(reconcile);
|
||||||
|
this.udpatePaymentTax(reconcile);
|
||||||
|
if (updateInvoicePayments) {
|
||||||
|
this.updateInvoicePayments(reconcile);
|
||||||
|
}
|
||||||
|
this.addToReconcileGroup(reconcile);
|
||||||
|
|
||||||
|
return reconcileRepository.save(reconcile);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,569 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.Reconcile;
|
||||||
|
import com.axelor.apps.account.db.Reimbursement;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReimbursementRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountService;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveLineService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.repo.BlockingRepository;
|
||||||
|
import com.axelor.apps.base.db.repo.PartnerRepository;
|
||||||
|
import com.axelor.apps.base.db.repo.SequenceRepository;
|
||||||
|
import com.axelor.apps.base.service.BlockingService;
|
||||||
|
import com.axelor.apps.base.service.PartnerService;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ReimbursementExportService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected MoveService moveService;
|
||||||
|
protected MoveRepository moveRepo;
|
||||||
|
protected MoveLineService moveLineService;
|
||||||
|
protected ReconcileService reconcileService;
|
||||||
|
protected SequenceService sequenceService;
|
||||||
|
protected ReimbursementRepository reimbursementRepo;
|
||||||
|
protected AccountConfigService accountConfigService;
|
||||||
|
protected PartnerService partnerService;
|
||||||
|
protected PartnerRepository partnerRepository;
|
||||||
|
protected AppAccountService appAccountService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ReimbursementExportService(
|
||||||
|
MoveService moveService,
|
||||||
|
MoveRepository moveRepo,
|
||||||
|
MoveLineService moveLineService,
|
||||||
|
ReconcileService reconcileService,
|
||||||
|
SequenceService sequenceService,
|
||||||
|
ReimbursementRepository reimbursementRepo,
|
||||||
|
AccountConfigService accountConfigService,
|
||||||
|
PartnerService partnerService,
|
||||||
|
AppAccountService appAccountService,
|
||||||
|
PartnerRepository partnerRepository) {
|
||||||
|
|
||||||
|
this.moveService = moveService;
|
||||||
|
this.moveRepo = moveRepo;
|
||||||
|
this.moveLineService = moveLineService;
|
||||||
|
this.reconcileService = reconcileService;
|
||||||
|
this.sequenceService = sequenceService;
|
||||||
|
this.reimbursementRepo = reimbursementRepo;
|
||||||
|
this.accountConfigService = accountConfigService;
|
||||||
|
this.partnerService = partnerService;
|
||||||
|
this.partnerRepository = partnerRepository;
|
||||||
|
this.appAccountService = appAccountService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param reimbursementExport */
|
||||||
|
public void fillMoveLineSet(
|
||||||
|
Reimbursement reimbursement, List<MoveLine> moveLineList, BigDecimal total) {
|
||||||
|
|
||||||
|
log.debug("In fillMoveLineSet");
|
||||||
|
log.debug("Nombre de trop-perçus trouvés : {}", moveLineList.size());
|
||||||
|
|
||||||
|
for (MoveLine moveLine : moveLineList) {
|
||||||
|
// On passe les lignes d'écriture (trop perçu) à l'état 'en cours de remboursement'
|
||||||
|
moveLine.setReimbursementStatusSelect(MoveLineRepository.REIMBURSEMENT_STATUS_REIMBURSING);
|
||||||
|
}
|
||||||
|
|
||||||
|
reimbursement.setMoveLineSet(new HashSet<MoveLine>());
|
||||||
|
reimbursement.getMoveLineSet().addAll(moveLineList);
|
||||||
|
|
||||||
|
log.debug("End fillMoveLineSet");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param reimbursementExport
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public Reimbursement runCreateReimbursement(
|
||||||
|
List<MoveLine> moveLineList, Company company, Partner partner) throws AxelorException {
|
||||||
|
|
||||||
|
log.debug("In runReimbursementProcess");
|
||||||
|
|
||||||
|
BigDecimal total = this.getTotalAmountRemaining(moveLineList);
|
||||||
|
|
||||||
|
AccountConfig accountConfig = company.getAccountConfig();
|
||||||
|
|
||||||
|
// Seuil bas respecté et remboursement manuel autorisé
|
||||||
|
if (total.compareTo(accountConfig.getLowerThresholdReimbursement()) > 0) {
|
||||||
|
|
||||||
|
Reimbursement reimbursement = createReimbursement(partner, company);
|
||||||
|
|
||||||
|
fillMoveLineSet(reimbursement, moveLineList, total);
|
||||||
|
|
||||||
|
if (total.compareTo(accountConfig.getUpperThresholdReimbursement()) > 0
|
||||||
|
|| reimbursement.getBankDetails() == null) {
|
||||||
|
// Seuil haut dépassé
|
||||||
|
reimbursement.setStatusSelect(ReimbursementRepository.STATUS_TO_VALIDATE);
|
||||||
|
} else {
|
||||||
|
reimbursement.setStatusSelect(ReimbursementRepository.STATUS_VALIDATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
reimbursement = reimbursementRepo.save(reimbursement);
|
||||||
|
return reimbursement;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("End runReimbursementProcess");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de calculer le montant total restant à payer / à lettrer
|
||||||
|
*
|
||||||
|
* @param movelineList Une liste de ligne d'écriture
|
||||||
|
* @return Le montant total restant à payer / à lettrer
|
||||||
|
*/
|
||||||
|
public BigDecimal getTotalAmountRemaining(List<MoveLine> moveLineList) {
|
||||||
|
BigDecimal total = BigDecimal.ZERO;
|
||||||
|
for (MoveLine moveLine : moveLineList) {
|
||||||
|
total = total.add(moveLine.getAmountRemaining());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Total Amount Remaining : {}", total);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode permettant de créer l'écriture de remboursement
|
||||||
|
*
|
||||||
|
* @param reimbursementExport Un objet d'export des prélèvements
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void createReimbursementMove(Reimbursement reimbursement, Company company)
|
||||||
|
throws AxelorException {
|
||||||
|
reimbursement = reimbursementRepo.find(reimbursement.getId());
|
||||||
|
|
||||||
|
Partner partner = null;
|
||||||
|
Move newMove = null;
|
||||||
|
boolean first = true;
|
||||||
|
|
||||||
|
AccountConfig accountConfig = company.getAccountConfig();
|
||||||
|
|
||||||
|
if (reimbursement.getMoveLineSet() != null && !reimbursement.getMoveLineSet().isEmpty()) {
|
||||||
|
int seq = 1;
|
||||||
|
for (MoveLine moveLine : reimbursement.getMoveLineSet()) {
|
||||||
|
BigDecimal amountRemaining = moveLine.getAmountRemaining();
|
||||||
|
if (amountRemaining.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
partner = moveLine.getPartner();
|
||||||
|
|
||||||
|
// On passe les lignes d'écriture (trop perçu) à l'état 'remboursé'
|
||||||
|
moveLine.setReimbursementStatusSelect(MoveLineRepository.REIMBURSEMENT_STATUS_REIMBURSED);
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
newMove =
|
||||||
|
moveService
|
||||||
|
.getMoveCreateService()
|
||||||
|
.createMove(
|
||||||
|
accountConfig.getReimbursementJournal(),
|
||||||
|
company,
|
||||||
|
null,
|
||||||
|
partner,
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
// Création d'une ligne au débit
|
||||||
|
MoveLine newDebitMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
newMove,
|
||||||
|
partner,
|
||||||
|
moveLine.getAccount(),
|
||||||
|
amountRemaining,
|
||||||
|
true,
|
||||||
|
appAccountService.getTodayDate(),
|
||||||
|
seq,
|
||||||
|
reimbursement.getRef(),
|
||||||
|
reimbursement.getDescription());
|
||||||
|
newMove.getMoveLineList().add(newDebitMoveLine);
|
||||||
|
if (reimbursement.getDescription() != null && !reimbursement.getDescription().isEmpty()) {
|
||||||
|
newDebitMoveLine.setDescription(reimbursement.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
seq++;
|
||||||
|
|
||||||
|
// Création de la réconciliation
|
||||||
|
Reconcile reconcile =
|
||||||
|
reconcileService.createReconcile(newDebitMoveLine, moveLine, amountRemaining, false);
|
||||||
|
if (reconcile != null) {
|
||||||
|
reconcileService.confirmReconcile(reconcile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Création de la ligne au crédit
|
||||||
|
MoveLine newCreditMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
newMove,
|
||||||
|
partner,
|
||||||
|
accountConfig.getReimbursementAccount(),
|
||||||
|
reimbursement.getAmountReimbursed(),
|
||||||
|
false,
|
||||||
|
appAccountService.getTodayDate(),
|
||||||
|
seq,
|
||||||
|
reimbursement.getRef(),
|
||||||
|
reimbursement.getDescription());
|
||||||
|
|
||||||
|
newMove.getMoveLineList().add(newCreditMoveLine);
|
||||||
|
if (reimbursement.getDescription() != null && !reimbursement.getDescription().isEmpty()) {
|
||||||
|
newCreditMoveLine.setDescription(reimbursement.getDescription());
|
||||||
|
}
|
||||||
|
moveService.getMoveValidateService().validate(newMove);
|
||||||
|
moveRepo.save(newMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de tester la présence des champs et des séquences nécessaire aux
|
||||||
|
* remboursements.
|
||||||
|
*
|
||||||
|
* @param company Une société
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void testCompanyField(Company company) throws AxelorException {
|
||||||
|
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
|
||||||
|
accountConfigService.getReimbursementAccount(accountConfig);
|
||||||
|
accountConfigService.getReimbursementJournal(accountConfig);
|
||||||
|
accountConfigService.getReimbursementExportFolderPath(accountConfig);
|
||||||
|
|
||||||
|
if (!sequenceService.hasSequence(SequenceRepository.REIMBOURSEMENT, company)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||||
|
I18n.get(IExceptionMessage.REIMBURSEMENT_1),
|
||||||
|
I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.EXCEPTION),
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void reimburse(Reimbursement reimbursement, Company company) throws AxelorException {
|
||||||
|
reimbursement.setAmountReimbursed(reimbursement.getAmountToReimburse());
|
||||||
|
this.createReimbursementMove(reimbursement, company);
|
||||||
|
reimbursement.setStatusSelect(ReimbursementRepository.STATUS_REIMBURSED);
|
||||||
|
reimbursementRepo.save(reimbursement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de créer un remboursement
|
||||||
|
*
|
||||||
|
* @param partner Un tiers
|
||||||
|
* @param company Une société
|
||||||
|
* @param reimbursementExport Un export des remboursement
|
||||||
|
* @return Le remboursmeent créé
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public Reimbursement createReimbursement(Partner partner, Company company)
|
||||||
|
throws AxelorException {
|
||||||
|
Reimbursement reimbursement = new Reimbursement();
|
||||||
|
reimbursement.setPartner(partner);
|
||||||
|
reimbursement.setCompany(company);
|
||||||
|
|
||||||
|
BankDetails bankDetails = partnerService.getDefaultBankDetails(partner);
|
||||||
|
|
||||||
|
reimbursement.setBankDetails(bankDetails);
|
||||||
|
|
||||||
|
reimbursement.setRef(
|
||||||
|
sequenceService.getSequenceNumber(SequenceRepository.REIMBOURSEMENT, company));
|
||||||
|
|
||||||
|
return reimbursement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the partner can be reimbursed
|
||||||
|
*
|
||||||
|
* @return true if partner can be reimbursed, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean canBeReimbursed(Partner partner, Company company) {
|
||||||
|
return Beans.get(BlockingService.class)
|
||||||
|
.getBlocking(partner, company, BlockingRepository.REIMBURSEMENT_BLOCKING)
|
||||||
|
== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de mettre à jour la liste des RIBs du tiers
|
||||||
|
*
|
||||||
|
* @param reimbursement Un remboursement
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void updatePartnerCurrentRIB(Reimbursement reimbursement) {
|
||||||
|
BankDetails bankDetails = reimbursement.getBankDetails();
|
||||||
|
Partner partner = reimbursement.getPartner();
|
||||||
|
BankDetails defaultBankDetails = partnerService.getDefaultBankDetails(partner);
|
||||||
|
|
||||||
|
if (partner != null && bankDetails != null && !bankDetails.equals(defaultBankDetails)) {
|
||||||
|
bankDetails.setIsDefault(true);
|
||||||
|
defaultBankDetails.setIsDefault(false);
|
||||||
|
partner.addBankDetailsListItem(bankDetails);
|
||||||
|
|
||||||
|
partnerRepository.save(partner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
/**
|
||||||
|
* Méthode permettant de créer un fichier xml de virement au format SEPA
|
||||||
|
* @param export
|
||||||
|
* @param datetime
|
||||||
|
* @param reimbursementList
|
||||||
|
* @throws AxelorException
|
||||||
|
* @throws DatatypeConfigurationException
|
||||||
|
* @throws JAXBException
|
||||||
|
* @throws IOException
|
||||||
|
public void exportSepa(Company company, ZonedDateTime datetime, List<Reimbursement> reimbursementList, BankDetails bankDetails) throws AxelorException, DatatypeConfigurationException, JAXBException, IOException {
|
||||||
|
|
||||||
|
String exportFolderPath = accountConfigService.getReimbursementExportFolderPath(accountConfigService.getAccountConfig(company));
|
||||||
|
|
||||||
|
if (exportFolderPath == null) {
|
||||||
|
throw new AxelorException(TraceBackRepository.CATEGORY_MISSING_FIELD, I18n.get(IExceptionMessage.REIMBURSEMENT_2), company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
|
||||||
|
Date date = Date.from(datetime.toInstant());
|
||||||
|
BigDecimal ctrlSum = BigDecimal.ZERO;
|
||||||
|
int nbOfTxs = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Création du documemnt XML en mémoire
|
||||||
|
-/
|
||||||
|
|
||||||
|
ObjectFactory factory = new ObjectFactory();
|
||||||
|
|
||||||
|
// Débit
|
||||||
|
|
||||||
|
// Paiement
|
||||||
|
ServiceLevel2Choice svcLvl = factory.createServiceLevel2Choice();
|
||||||
|
svcLvl.setCd(ServiceLevel1Code.SEPA);
|
||||||
|
|
||||||
|
PaymentTypeInformation1 pmtTpInf = factory.createPaymentTypeInformation1();
|
||||||
|
pmtTpInf.setSvcLvl(svcLvl);
|
||||||
|
|
||||||
|
// Payeur
|
||||||
|
PartyIdentification8 dbtr = factory.createPartyIdentification8();
|
||||||
|
dbtr.setNm(bankDetails.getOwnerName());
|
||||||
|
|
||||||
|
// IBAN
|
||||||
|
AccountIdentification3Choice iban = factory.createAccountIdentification3Choice();
|
||||||
|
iban.setIBAN(bankDetails.getIban());
|
||||||
|
|
||||||
|
CashAccount7 dbtrAcct = factory.createCashAccount7();
|
||||||
|
dbtrAcct.setId(iban);
|
||||||
|
|
||||||
|
// BIC
|
||||||
|
FinancialInstitutionIdentification5Choice finInstnId = factory.createFinancialInstitutionIdentification5Choice();
|
||||||
|
finInstnId.setBIC(bankDetails.getBank().getCode());
|
||||||
|
|
||||||
|
BranchAndFinancialInstitutionIdentification3 dbtrAgt = factory.createBranchAndFinancialInstitutionIdentification3();
|
||||||
|
dbtrAgt.setFinInstnId(finInstnId);
|
||||||
|
|
||||||
|
// Lot
|
||||||
|
|
||||||
|
PaymentInstructionInformation1 pmtInf = factory.createPaymentInstructionInformation1();
|
||||||
|
pmtInf.setPmtMtd(PaymentMethod3Code.TRF);
|
||||||
|
pmtInf.setPmtTpInf(pmtTpInf);
|
||||||
|
pmtInf.setReqdExctnDt(datatypeFactory.newXMLGregorianCalendar(dateFormat.format(date)));
|
||||||
|
pmtInf.setDbtr(dbtr);
|
||||||
|
pmtInf.setDbtrAcct(dbtrAcct);
|
||||||
|
pmtInf.setDbtrAgt(dbtrAgt);
|
||||||
|
|
||||||
|
// Crédit
|
||||||
|
CreditTransferTransactionInformation1 cdtTrfTxInf = null; PaymentIdentification1 pmtId = null;
|
||||||
|
AmountType2Choice amt = null; CurrencyAndAmount instdAmt = null;
|
||||||
|
PartyIdentification8 cbtr = null; CashAccount7 cbtrAcct = null;
|
||||||
|
BranchAndFinancialInstitutionIdentification3 cbtrAgt = null;
|
||||||
|
RemittanceInformation1 rmtInf = null;
|
||||||
|
for (Reimbursement reimbursement : reimbursementList){
|
||||||
|
|
||||||
|
reimbursement = reimbursementRepo.find(reimbursement.getId());
|
||||||
|
|
||||||
|
nbOfTxs++;
|
||||||
|
ctrlSum = ctrlSum.add(reimbursement.getAmountReimbursed());
|
||||||
|
bankDetails = reimbursement.getBankDetails();
|
||||||
|
|
||||||
|
// Paiement
|
||||||
|
pmtId = factory.createPaymentIdentification1();
|
||||||
|
pmtId.setEndToEndId(reimbursement.getRef());
|
||||||
|
|
||||||
|
// Montant
|
||||||
|
instdAmt = factory.createCurrencyAndAmount();
|
||||||
|
instdAmt.setCcy("EUR");
|
||||||
|
instdAmt.setValue(reimbursement.getAmountReimbursed());
|
||||||
|
|
||||||
|
amt = factory.createAmountType2Choice();
|
||||||
|
amt.setInstdAmt(instdAmt);
|
||||||
|
|
||||||
|
// Débiteur
|
||||||
|
cbtr = factory.createPartyIdentification8();
|
||||||
|
cbtr.setNm(bankDetails.getOwnerName());
|
||||||
|
|
||||||
|
// IBAN
|
||||||
|
iban = factory.createAccountIdentification3Choice();
|
||||||
|
iban.setIBAN(bankDetails.getIban());
|
||||||
|
|
||||||
|
cbtrAcct = factory.createCashAccount7();
|
||||||
|
cbtrAcct.setId(iban);
|
||||||
|
|
||||||
|
// BIC
|
||||||
|
finInstnId = factory.createFinancialInstitutionIdentification5Choice();
|
||||||
|
finInstnId.setBIC(bankDetails.getBank().getCode());
|
||||||
|
|
||||||
|
cbtrAgt = factory.createBranchAndFinancialInstitutionIdentification3();
|
||||||
|
cbtrAgt.setFinInstnId(finInstnId);
|
||||||
|
|
||||||
|
rmtInf = factory.createRemittanceInformation1();
|
||||||
|
|
||||||
|
rmtInf.getUstrd().add(reimbursement.getDescription());
|
||||||
|
|
||||||
|
// Transaction
|
||||||
|
cdtTrfTxInf = factory.createCreditTransferTransactionInformation1();
|
||||||
|
cdtTrfTxInf.setPmtId(pmtId);
|
||||||
|
cdtTrfTxInf.setAmt(amt);
|
||||||
|
cdtTrfTxInf.setCdtr(cbtr);
|
||||||
|
cdtTrfTxInf.setCdtrAcct(cbtrAcct);
|
||||||
|
cdtTrfTxInf.setCdtrAgt(cbtrAgt);
|
||||||
|
cdtTrfTxInf.setRmtInf(rmtInf);
|
||||||
|
|
||||||
|
pmtInf.getCdtTrfTxInf().add(cdtTrfTxInf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// En-tête
|
||||||
|
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
|
||||||
|
GroupHeader1 grpHdr = factory.createGroupHeader1();
|
||||||
|
grpHdr.setCreDtTm(datatypeFactory.newXMLGregorianCalendar(dateFormat.format(date)));
|
||||||
|
grpHdr.setNbOfTxs(Integer.toString(nbOfTxs));
|
||||||
|
grpHdr.setCtrlSum(ctrlSum);
|
||||||
|
grpHdr.setGrpg(Grouping1Code.MIXD);
|
||||||
|
grpHdr.setInitgPty(dbtr);
|
||||||
|
|
||||||
|
// Parent
|
||||||
|
Pain00100102 pain00100102 = factory.createPain00100102();
|
||||||
|
pain00100102.setGrpHdr(grpHdr);
|
||||||
|
pain00100102.getPmtInf().add(pmtInf);
|
||||||
|
|
||||||
|
// Document
|
||||||
|
Document xml = factory.createDocument();
|
||||||
|
xml.setPain00100102(pain00100102);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Création du documemnt XML physique
|
||||||
|
-/
|
||||||
|
Marschaller.marschalFile(factory.createDocument(xml), "com.axelor.apps.xsd.sepa",
|
||||||
|
exportFolderPath, String.format("%s.xml", dateFormat.format(date)));
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* *********************** Remboursement lors d'une facture fin de cycle
|
||||||
|
* ********************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de créer un remboursement si un trop perçu est généré à la facture fin de
|
||||||
|
* cycle
|
||||||
|
*
|
||||||
|
* @param partner Un tiers
|
||||||
|
* @param company Une société
|
||||||
|
* @param moveLine Un trop-perçu
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void createReimbursementInvoice(
|
||||||
|
Partner partner, Company company, List<? extends MoveLine> moveLineList)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
BigDecimal total = this.getTotalAmountRemaining((List<MoveLine>) moveLineList);
|
||||||
|
|
||||||
|
if (total.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
|
||||||
|
this.testCompanyField(company);
|
||||||
|
|
||||||
|
Reimbursement reimbursement = this.createReimbursement(partner, company);
|
||||||
|
|
||||||
|
this.fillMoveLineSet(reimbursement, (List<MoveLine>) moveLineList, total);
|
||||||
|
|
||||||
|
if (total.compareTo(company.getAccountConfig().getUpperThresholdReimbursement()) > 0
|
||||||
|
|| reimbursement.getBankDetails() == null) {
|
||||||
|
// Seuil haut dépassé
|
||||||
|
reimbursement.setStatusSelect(ReimbursementRepository.STATUS_TO_VALIDATE);
|
||||||
|
} else {
|
||||||
|
// Seuil haut non dépassé
|
||||||
|
reimbursement.setStatusSelect(ReimbursementRepository.STATUS_VALIDATED);
|
||||||
|
}
|
||||||
|
reimbursementRepo.save(reimbursement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de créer un remboursement si un trop perçu est généré à la facture fin de
|
||||||
|
* cycle grand comptes
|
||||||
|
*
|
||||||
|
* @param invoice Une facture
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void createReimbursementInvoice(Invoice invoice) throws AxelorException {
|
||||||
|
Company company = invoice.getCompany();
|
||||||
|
Partner partner = invoice.getPartner();
|
||||||
|
MoveLineRepository moveLineRepo = Beans.get(MoveLineRepository.class);
|
||||||
|
// récupération des trop-perçus du tiers
|
||||||
|
List<? extends MoveLine> moveLineList =
|
||||||
|
moveLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.account.useForPartnerBalance = 'true' "
|
||||||
|
+ "AND (self.move.statusSelect = ?1 OR self.move.statusSelect = ?2) AND self.amountRemaining > 0 AND self.credit > 0 AND self.partner = ?3 AND self.reimbursementStatusSelect = ?4 ",
|
||||||
|
MoveRepository.STATUS_VALIDATED,
|
||||||
|
MoveRepository.STATUS_DAYBOOK,
|
||||||
|
partner,
|
||||||
|
MoveLineRepository.REIMBURSEMENT_STATUS_NULL)
|
||||||
|
.fetch();
|
||||||
|
|
||||||
|
this.createReimbursementInvoice(partner, company, moveLineList);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.InterbankCodeLine;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.Reimbursement;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveLineRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.ReimbursementRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveLineService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ReimbursementImportService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected MoveService moveService;
|
||||||
|
protected MoveRepository moveRepo;
|
||||||
|
protected MoveLineService moveLineService;
|
||||||
|
protected RejectImportService rejectImportService;
|
||||||
|
protected AccountConfigService accountConfigService;
|
||||||
|
protected ReimbursementRepository reimbursementRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ReimbursementImportService(
|
||||||
|
MoveService moveService,
|
||||||
|
MoveRepository moveRepo,
|
||||||
|
MoveLineService moveLineService,
|
||||||
|
RejectImportService rejectImportService,
|
||||||
|
AccountConfigService accountConfigService,
|
||||||
|
ReimbursementRepository reimbursementRepo) {
|
||||||
|
|
||||||
|
this.moveService = moveService;
|
||||||
|
this.moveRepo = moveRepo;
|
||||||
|
this.moveLineService = moveLineService;
|
||||||
|
this.rejectImportService = rejectImportService;
|
||||||
|
this.accountConfigService = accountConfigService;
|
||||||
|
this.reimbursementRepo = reimbursementRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void runReimbursementImport(Company company) throws AxelorException, IOException {
|
||||||
|
|
||||||
|
this.testCompanyField(company);
|
||||||
|
|
||||||
|
AccountConfig accountConfig = company.getAccountConfig();
|
||||||
|
|
||||||
|
this.createReimbursementRejectMove(
|
||||||
|
rejectImportService.getCFONBFile(
|
||||||
|
accountConfig.getReimbursementImportFolderPathCFONB(),
|
||||||
|
accountConfig.getTempReimbImportFolderPathCFONB(),
|
||||||
|
company,
|
||||||
|
0),
|
||||||
|
company);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createReimbursementRejectMove(List<String[]> rejectList, Company company)
|
||||||
|
throws AxelorException {
|
||||||
|
int seq = 1;
|
||||||
|
if (rejectList != null && !rejectList.isEmpty()) {
|
||||||
|
LocalDate rejectDate = rejectImportService.createRejectDate(rejectList.get(0)[0]);
|
||||||
|
Move move = this.createMoveReject(company, rejectDate);
|
||||||
|
for (String[] reject : rejectList) {
|
||||||
|
|
||||||
|
this.createReimbursementRejectMoveLine(reject, company, seq, move, rejectDate);
|
||||||
|
seq++;
|
||||||
|
}
|
||||||
|
if (move != null) {
|
||||||
|
// Création d'une ligne au débit
|
||||||
|
MoveLine debitMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
null,
|
||||||
|
company.getAccountConfig().getReimbursementAccount(),
|
||||||
|
this.getTotalAmount(move),
|
||||||
|
true,
|
||||||
|
rejectDate,
|
||||||
|
seq,
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
move.getMoveLineList().add(debitMoveLine);
|
||||||
|
this.validateMove(move);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public Reimbursement createReimbursementRejectMoveLine(
|
||||||
|
String[] reject, Company company, int seq, Move move, LocalDate rejectDate)
|
||||||
|
throws AxelorException {
|
||||||
|
|
||||||
|
String refReject = reject[1];
|
||||||
|
// String amountReject = reject[2];
|
||||||
|
InterbankCodeLine causeReject = rejectImportService.getInterbankCodeLine(reject[3], 0);
|
||||||
|
MoveLineRepository moveLineRepo = Beans.get(MoveLineRepository.class);
|
||||||
|
|
||||||
|
Reimbursement reimbursement =
|
||||||
|
reimbursementRepo
|
||||||
|
.all()
|
||||||
|
.filter("UPPER(self.ref) = ?1 AND self.company = ?2", refReject, company)
|
||||||
|
.fetchOne();
|
||||||
|
if (reimbursement == null) {
|
||||||
|
throw new AxelorException(
|
||||||
|
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||||
|
I18n.get(IExceptionMessage.REIMBURSEMENT_3),
|
||||||
|
refReject,
|
||||||
|
company.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Partner partner = reimbursement.getPartner();
|
||||||
|
BigDecimal amount = reimbursement.getAmountReimbursed();
|
||||||
|
|
||||||
|
// Création de la ligne au crédit
|
||||||
|
MoveLine creditMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
partner,
|
||||||
|
company.getAccountConfig().getCustomerAccount(),
|
||||||
|
amount,
|
||||||
|
false,
|
||||||
|
rejectDate,
|
||||||
|
seq,
|
||||||
|
refReject,
|
||||||
|
null);
|
||||||
|
move.getMoveLineList().add(creditMoveLine);
|
||||||
|
|
||||||
|
moveLineRepo.save(creditMoveLine);
|
||||||
|
|
||||||
|
moveRepo.save(move);
|
||||||
|
creditMoveLine.setInterbankCodeLine(causeReject);
|
||||||
|
|
||||||
|
reimbursement.setRejectedOk(true);
|
||||||
|
reimbursement.setRejectDate(rejectDate);
|
||||||
|
reimbursement.setRejectMoveLine(creditMoveLine);
|
||||||
|
reimbursement.setInterbankCodeLine(causeReject);
|
||||||
|
reimbursementRepo.save(reimbursement);
|
||||||
|
|
||||||
|
return reimbursement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public Move createMoveReject(Company company, LocalDate date) throws AxelorException {
|
||||||
|
return moveRepo.save(
|
||||||
|
moveService
|
||||||
|
.getMoveCreateService()
|
||||||
|
.createMove(
|
||||||
|
company.getAccountConfig().getRejectJournal(),
|
||||||
|
company,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_IMPORT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getTotalAmount(Move move) {
|
||||||
|
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
for (MoveLine moveLine : move.getMoveLineList()) {
|
||||||
|
totalAmount = totalAmount.add(moveLine.getCredit());
|
||||||
|
}
|
||||||
|
return totalAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public MoveLine createOppositeRejectMoveLine(Move move, int seq, LocalDate rejectDate)
|
||||||
|
throws AxelorException {
|
||||||
|
// Création d'une ligne au débit
|
||||||
|
MoveLine debitMoveLine =
|
||||||
|
moveLineService.createMoveLine(
|
||||||
|
move,
|
||||||
|
null,
|
||||||
|
move.getCompany().getAccountConfig().getReimbursementAccount(),
|
||||||
|
this.getTotalAmount(move),
|
||||||
|
true,
|
||||||
|
rejectDate,
|
||||||
|
seq,
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
move.getMoveLineList().add(debitMoveLine);
|
||||||
|
moveRepo.save(move);
|
||||||
|
return debitMoveLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void validateMove(Move move) throws AxelorException {
|
||||||
|
moveService.getMoveValidateService().validate(move);
|
||||||
|
moveRepo.save(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteMove(Move move) {
|
||||||
|
moveRepo.remove(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de tester la présence des champs et des séquences nécessaire aux rejets de
|
||||||
|
* remboursement.
|
||||||
|
*
|
||||||
|
* @param company Une société
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
public void testCompanyField(Company company) throws AxelorException {
|
||||||
|
log.debug("Test de la société {}", company.getName());
|
||||||
|
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
|
||||||
|
accountConfigService.getReimbursementAccount(accountConfig);
|
||||||
|
accountConfigService.getRejectJournal(accountConfig);
|
||||||
|
accountConfigService.getReimbursementImportFolderPathCFONB(accountConfig);
|
||||||
|
accountConfigService.getTempReimbImportFolderPathCFONB(accountConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Reimbursement;
|
||||||
|
import com.axelor.apps.base.db.BankDetails;
|
||||||
|
import com.axelor.apps.base.db.Partner;
|
||||||
|
import com.axelor.apps.base.db.repo.PartnerRepository;
|
||||||
|
import com.axelor.apps.base.service.PartnerService;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
|
||||||
|
public class ReimbursementService {
|
||||||
|
|
||||||
|
protected PartnerRepository partnerRepository;
|
||||||
|
protected PartnerService partnerService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ReimbursementService(PartnerRepository partnerRepository, PartnerService partnerService) {
|
||||||
|
|
||||||
|
this.partnerRepository = partnerRepository;
|
||||||
|
this.partnerService = partnerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Procédure permettant de mettre à jour la liste des RIBs du tiers
|
||||||
|
*
|
||||||
|
* @param reimbursement Un remboursement
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void updatePartnerCurrentRIB(Reimbursement reimbursement) {
|
||||||
|
BankDetails bankDetails = reimbursement.getBankDetails();
|
||||||
|
Partner partner = reimbursement.getPartner();
|
||||||
|
BankDetails defaultBankDetails = partnerService.getDefaultBankDetails(partner);
|
||||||
|
|
||||||
|
if (bankDetails != null && partner != null && !bankDetails.equals(defaultBankDetails)) {
|
||||||
|
defaultBankDetails.setIsDefault(false);
|
||||||
|
bankDetails.setIsDefault(true);
|
||||||
|
partner.addBankDetailsListItem(bankDetails);
|
||||||
|
partnerRepository.save(partner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,216 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.InterbankCodeLine;
|
||||||
|
import com.axelor.apps.account.db.repo.InterbankCodeLineRepository;
|
||||||
|
import com.axelor.apps.account.service.app.AppAccountService;
|
||||||
|
import com.axelor.apps.account.service.bankorder.file.cfonb.CfonbImportService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.tool.file.FileTool;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class RejectImportService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
protected AppAccountService appAccountService;
|
||||||
|
protected CfonbImportService cfonbImportService;
|
||||||
|
protected InterbankCodeLineRepository interbankCodeLineRepo;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public RejectImportService(
|
||||||
|
AppAccountService appAccountService,
|
||||||
|
CfonbImportService cfonbImportService,
|
||||||
|
InterbankCodeLineRepository interbankCodeLineRepo) {
|
||||||
|
|
||||||
|
this.appAccountService = appAccountService;
|
||||||
|
this.cfonbImportService = cfonbImportService;
|
||||||
|
this.interbankCodeLineRepo = interbankCodeLineRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDestFilename(String src, String dest) {
|
||||||
|
// chemin du fichier de destination :
|
||||||
|
log.debug("Chemin de destination : {}", dest);
|
||||||
|
String newDest = ((dest).split("\\."))[0];
|
||||||
|
String timeString = appAccountService.getTodayDateTime().toString();
|
||||||
|
timeString = timeString.replace("-", "");
|
||||||
|
timeString = timeString.replace(":", "");
|
||||||
|
timeString = timeString.replace(".", "");
|
||||||
|
timeString = timeString.replace("+", "");
|
||||||
|
|
||||||
|
newDest += "_" + timeString + ".";
|
||||||
|
|
||||||
|
if (dest.split("\\.").length == 2) {
|
||||||
|
newDest += dest.split("\\.")[1];
|
||||||
|
} else {
|
||||||
|
newDest += src.split("\\.")[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Chemin de destination généré : {}", newDest);
|
||||||
|
|
||||||
|
return newDest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDestCFONBFile(String src, String temp) throws AxelorException, IOException {
|
||||||
|
String dest = this.getDestFilename(src, temp);
|
||||||
|
|
||||||
|
this.createFilePath(dest);
|
||||||
|
|
||||||
|
// copie du fichier d'import dans un repetoire temporaire
|
||||||
|
FileTool.copy(src, dest);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param src
|
||||||
|
* @param temp
|
||||||
|
* @param company
|
||||||
|
* @param operation Le type d'opération :
|
||||||
|
* <ul>
|
||||||
|
* <li>0 = Virement
|
||||||
|
* <li>1 = Prélèvement
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public List<String[]> getCFONBFile(String src, String temp, Company company, int operation)
|
||||||
|
throws AxelorException, IOException {
|
||||||
|
|
||||||
|
String dest = this.getDestCFONBFile(src, temp);
|
||||||
|
|
||||||
|
return cfonbImportService.importCFONB(dest, company, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param src
|
||||||
|
* @param temp
|
||||||
|
* @param company
|
||||||
|
* @param operation Le type d'opération :
|
||||||
|
* <ul>
|
||||||
|
* <li>0 = Virement
|
||||||
|
* <li>1 = Prélèvement
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public Map<List<String[]>, String> getCFONBFileByLot(
|
||||||
|
String src, String temp, Company company, int operation) throws AxelorException, IOException {
|
||||||
|
|
||||||
|
String dest = this.getDestCFONBFile(src, temp);
|
||||||
|
|
||||||
|
return cfonbImportService.importCFONBByLot(dest, company, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de récupérer le motif de rejet/retour
|
||||||
|
*
|
||||||
|
* @param reasonCode Un code motifs de rejet/retour
|
||||||
|
* @param interbankCodeOperation Le type d'opération :
|
||||||
|
* <ul>
|
||||||
|
* <li>0 = Virement
|
||||||
|
* <li>1 = Prélèvement/TIP/Télérèglement
|
||||||
|
* <li>2 = Prélèvement SEPA
|
||||||
|
* <li>3 = LCR/BOR
|
||||||
|
* <li>4 = Cheque
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return Un motif de rejet/retour
|
||||||
|
*/
|
||||||
|
public InterbankCodeLine getInterbankCodeLine(String reasonCode, int interbankCodeOperation) {
|
||||||
|
switch (interbankCodeOperation) {
|
||||||
|
case 0:
|
||||||
|
return interbankCodeLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.code = ?1 AND self.interbankCode = ?2 AND self.transferCfonbOk = 'true'",
|
||||||
|
reasonCode,
|
||||||
|
appAccountService.getAppAccount().getTransferAndDirectDebitInterbankCode())
|
||||||
|
.fetchOne();
|
||||||
|
case 1:
|
||||||
|
return interbankCodeLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.code = ?1 AND self.interbankCode = ?2 AND self.directDebitAndTipCfonbOk = 'true'",
|
||||||
|
reasonCode,
|
||||||
|
appAccountService.getAppAccount().getTransferAndDirectDebitInterbankCode())
|
||||||
|
.fetchOne();
|
||||||
|
case 2:
|
||||||
|
return interbankCodeLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.code = ?1 AND self.interbankCode = ?2 AND self.directDebitSepaOk = 'true'",
|
||||||
|
reasonCode,
|
||||||
|
appAccountService.getAppAccount().getTransferAndDirectDebitInterbankCode())
|
||||||
|
.fetchOne();
|
||||||
|
case 3:
|
||||||
|
return interbankCodeLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.code = ?1 AND self.interbankCode = ?2 AND self.lcrBorOk = 'true'",
|
||||||
|
reasonCode,
|
||||||
|
appAccountService.getAppAccount().getTransferAndDirectDebitInterbankCode())
|
||||||
|
.fetchOne();
|
||||||
|
case 4:
|
||||||
|
return interbankCodeLineRepo
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.code = ?1 AND self.interbankCode = ?2 AND self.chequeOk = 'true'",
|
||||||
|
reasonCode,
|
||||||
|
appAccountService.getAppAccount().getChequeInterbankCode())
|
||||||
|
.fetchOne();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de construire une date de rejet depuis le texte récupéré du fichier CFONB
|
||||||
|
*
|
||||||
|
* @param dateReject
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public LocalDate createRejectDate(String dateReject) {
|
||||||
|
return LocalDate.of(
|
||||||
|
Integer.parseInt(dateReject.substring(4, 6)) + 2000,
|
||||||
|
Integer.parseInt(dateReject.substring(2, 4)),
|
||||||
|
Integer.parseInt(dateReject.substring(0, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createFilePath(String path) throws IOException {
|
||||||
|
|
||||||
|
File file = new File(path);
|
||||||
|
Files.createParentDirs(file);
|
||||||
|
file.createNewFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.SubrogationRelease;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface SubrogationReleaseService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve ventilated invoices from factorized customers.
|
||||||
|
*
|
||||||
|
* @param company
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<Invoice> retrieveInvoices(Company company);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit a subrogation release (generate a sequence number and change status).
|
||||||
|
*
|
||||||
|
* @param subrogationRelease
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
void transmitRelease(SubrogationRelease subrogationRelease) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a PDF export.
|
||||||
|
*
|
||||||
|
* @param subrogationRelease
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
String printToPDF(SubrogationRelease subrogationRelease, String name) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a CSV export.
|
||||||
|
*
|
||||||
|
* @param subrogationRelease
|
||||||
|
* @return
|
||||||
|
* @throws AxelorException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
String exportToCSV(SubrogationRelease subrogationRelease) throws AxelorException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter a subrogation release in the accounts (create moves).
|
||||||
|
*
|
||||||
|
* @param subrogationRelease
|
||||||
|
* @throws AxelorException
|
||||||
|
*/
|
||||||
|
void enterReleaseInTheAccounts(SubrogationRelease subrogationRelease) throws AxelorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the subrogation release
|
||||||
|
*
|
||||||
|
* @param subrogationRelease
|
||||||
|
*/
|
||||||
|
void clear(SubrogationRelease subrogationRelease);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the all invoice of the subrogation release are completely cleared
|
||||||
|
*
|
||||||
|
* @param subrogationRelease
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean isSubrogationReleaseCompletelyPaid(SubrogationRelease subrogationRelease);
|
||||||
|
}
|
||||||
@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
* Axelor Business Solutions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License, version 3,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.axelor.apps.account.service;
|
||||||
|
|
||||||
|
import com.axelor.apps.ReportFactory;
|
||||||
|
import com.axelor.apps.account.db.Account;
|
||||||
|
import com.axelor.apps.account.db.AccountConfig;
|
||||||
|
import com.axelor.apps.account.db.Invoice;
|
||||||
|
import com.axelor.apps.account.db.Journal;
|
||||||
|
import com.axelor.apps.account.db.Move;
|
||||||
|
import com.axelor.apps.account.db.MoveLine;
|
||||||
|
import com.axelor.apps.account.db.SubrogationRelease;
|
||||||
|
import com.axelor.apps.account.db.repo.InvoiceRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.MoveRepository;
|
||||||
|
import com.axelor.apps.account.db.repo.SubrogationReleaseRepository;
|
||||||
|
import com.axelor.apps.account.exception.IExceptionMessage;
|
||||||
|
import com.axelor.apps.account.report.IReport;
|
||||||
|
import com.axelor.apps.account.service.config.AccountConfigService;
|
||||||
|
import com.axelor.apps.account.service.invoice.InvoiceToolService;
|
||||||
|
import com.axelor.apps.account.service.move.MoveService;
|
||||||
|
import com.axelor.apps.base.db.Company;
|
||||||
|
import com.axelor.apps.base.db.Sequence;
|
||||||
|
import com.axelor.apps.base.service.administration.SequenceService;
|
||||||
|
import com.axelor.apps.base.service.app.AppBaseService;
|
||||||
|
import com.axelor.apps.report.engine.ReportSettings;
|
||||||
|
import com.axelor.apps.tool.file.CsvTool;
|
||||||
|
import com.axelor.db.Query;
|
||||||
|
import com.axelor.exception.AxelorException;
|
||||||
|
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||||
|
import com.axelor.i18n.I18n;
|
||||||
|
import com.axelor.inject.Beans;
|
||||||
|
import com.axelor.meta.MetaFiles;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.persist.Transactional;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class SubrogationReleaseServiceImpl implements SubrogationReleaseService {
|
||||||
|
|
||||||
|
protected AppBaseService appBaseService;
|
||||||
|
protected InvoiceRepository invoiceRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public SubrogationReleaseServiceImpl(
|
||||||
|
AppBaseService appBaseService, InvoiceRepository invoiceRepository) {
|
||||||
|
this.appBaseService = appBaseService;
|
||||||
|
this.invoiceRepository = invoiceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Invoice> retrieveInvoices(Company company) {
|
||||||
|
Query<Invoice> query =
|
||||||
|
invoiceRepository
|
||||||
|
.all()
|
||||||
|
.filter(
|
||||||
|
"self.company = :company AND self.partner.factorizedCustomer = TRUE "
|
||||||
|
+ "AND self.statusSelect = :invoiceStatusVentilated "
|
||||||
|
+ "AND self.id not in ("
|
||||||
|
+ " select Invoices.id "
|
||||||
|
+ " from SubrogationRelease as SR "
|
||||||
|
+ " join SR.invoiceSet as Invoices "
|
||||||
|
+ " where SR.statusSelect in (:subrogationReleaseStatusTransmitted, :subrogationReleaseStatusAccounted, :subrogationReleaseStatusCleared))"
|
||||||
|
+ "AND ((self.amountRemaining > 0 AND self.hasPendingPayments = FALSE)"
|
||||||
|
+ " OR self.originalInvoice.id in ("
|
||||||
|
+ " select Invoices.id "
|
||||||
|
+ " from SubrogationRelease as SR "
|
||||||
|
+ " join SR.invoiceSet as Invoices "
|
||||||
|
+ " where SR.statusSelect in (:subrogationReleaseStatusTransmitted, :subrogationReleaseStatusAccounted, :subrogationReleaseStatusCleared)))")
|
||||||
|
.order("invoiceDate")
|
||||||
|
.order("dueDate")
|
||||||
|
.order("invoiceId");
|
||||||
|
query.bind("company", company);
|
||||||
|
query.bind("invoiceStatusVentilated", InvoiceRepository.STATUS_VENTILATED);
|
||||||
|
query.bind(
|
||||||
|
"subrogationReleaseStatusTransmitted", SubrogationReleaseRepository.STATUS_TRANSMITTED);
|
||||||
|
query.bind("subrogationReleaseStatusAccounted", SubrogationReleaseRepository.STATUS_ACCOUNTED);
|
||||||
|
query.bind("subrogationReleaseStatusCleared", SubrogationReleaseRepository.STATUS_CLEARED);
|
||||||
|
List<Invoice> invoiceList = query.fetch();
|
||||||
|
return invoiceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void transmitRelease(SubrogationRelease subrogationRelease) throws AxelorException {
|
||||||
|
SequenceService sequenceService = Beans.get(SequenceService.class);
|
||||||
|
String sequenceNumber =
|
||||||
|
sequenceService.getSequenceNumber("subrogationRelease", subrogationRelease.getCompany());
|
||||||
|
if (Strings.isNullOrEmpty(sequenceNumber)) {
|
||||||
|
throw new AxelorException(
|
||||||
|
Sequence.class,
|
||||||
|
TraceBackRepository.CATEGORY_NO_VALUE,
|
||||||
|
I18n.get(IExceptionMessage.SUBROGATION_RELEASE_MISSING_SEQUENCE),
|
||||||
|
subrogationRelease.getCompany().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
subrogationRelease.setSequenceNumber(sequenceNumber);
|
||||||
|
subrogationRelease.setStatusSelect(SubrogationReleaseRepository.STATUS_TRANSMITTED);
|
||||||
|
subrogationRelease.setTransmissionDate(appBaseService.getTodayDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String printToPDF(SubrogationRelease subrogationRelease, String name)
|
||||||
|
throws AxelorException {
|
||||||
|
ReportSettings reportSettings = ReportFactory.createReport(IReport.SUBROGATION_RELEASE, name);
|
||||||
|
reportSettings.addParam("SubrogationReleaseId", subrogationRelease.getId());
|
||||||
|
reportSettings.addParam("Locale", ReportSettings.getPrintingLocale(null));
|
||||||
|
reportSettings.addFormat("pdf");
|
||||||
|
reportSettings.toAttach(subrogationRelease);
|
||||||
|
reportSettings.generate();
|
||||||
|
return reportSettings.getFileLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String exportToCSV(SubrogationRelease subrogationRelease)
|
||||||
|
throws AxelorException, IOException {
|
||||||
|
List<String[]> allMoveLineData = new ArrayList<>();
|
||||||
|
|
||||||
|
Comparator<Invoice> byInvoiceDate =
|
||||||
|
(i1, i2) -> i1.getInvoiceDate().compareTo(i2.getInvoiceDate());
|
||||||
|
Comparator<Invoice> byDueDate = (i1, i2) -> i1.getDueDate().compareTo(i2.getDueDate());
|
||||||
|
Comparator<Invoice> byInvoiceId = (i1, i2) -> i1.getInvoiceId().compareTo(i2.getInvoiceId());
|
||||||
|
|
||||||
|
List<Invoice> releaseDetails =
|
||||||
|
subrogationRelease
|
||||||
|
.getInvoiceSet()
|
||||||
|
.stream()
|
||||||
|
.sorted(byInvoiceDate.thenComparing(byDueDate).thenComparing(byInvoiceId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (Invoice invoice : releaseDetails) {
|
||||||
|
String[] items = new String[6];
|
||||||
|
BigDecimal inTaxTotal = invoice.getInTaxTotal().abs();
|
||||||
|
|
||||||
|
if (InvoiceToolService.isOutPayment(invoice)) {
|
||||||
|
inTaxTotal = inTaxTotal.negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
items[0] = invoice.getPartner().getPartnerSeq();
|
||||||
|
items[1] = invoice.getInvoiceId();
|
||||||
|
items[2] = invoice.getInvoiceDate().toString();
|
||||||
|
items[3] = invoice.getDueDate().toString();
|
||||||
|
items[4] = inTaxTotal.toString();
|
||||||
|
items[5] = invoice.getCurrency().getCode();
|
||||||
|
allMoveLineData.add(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountConfigService accountConfigService = Beans.get(AccountConfigService.class);
|
||||||
|
String filePath =
|
||||||
|
accountConfigService.getAccountConfig(subrogationRelease.getCompany()).getExportPath();
|
||||||
|
if (filePath == null) {
|
||||||
|
filePath = com.google.common.io.Files.createTempDir().getAbsolutePath();
|
||||||
|
} else {
|
||||||
|
new File(filePath).mkdirs();
|
||||||
|
}
|
||||||
|
String fileName =
|
||||||
|
String.format(
|
||||||
|
"%s %s.csv", I18n.get("Subrogation release"), subrogationRelease.getSequenceNumber());
|
||||||
|
Files.createDirectories(Paths.get(filePath));
|
||||||
|
Path path = Paths.get(filePath, fileName);
|
||||||
|
CsvTool.csvWriter(filePath, fileName, ';', null, allMoveLineData);
|
||||||
|
|
||||||
|
try (InputStream is = new FileInputStream(path.toFile())) {
|
||||||
|
Beans.get(MetaFiles.class).attach(is, fileName, subrogationRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackOn = {Exception.class})
|
||||||
|
public void enterReleaseInTheAccounts(SubrogationRelease subrogationRelease)
|
||||||
|
throws AxelorException {
|
||||||
|
MoveService moveService = Beans.get(MoveService.class);
|
||||||
|
MoveRepository moveRepository = Beans.get(MoveRepository.class);
|
||||||
|
AccountConfigService accountConfigService = Beans.get(AccountConfigService.class);
|
||||||
|
AppBaseService appBaseService = Beans.get(AppBaseService.class);
|
||||||
|
|
||||||
|
Company company = subrogationRelease.getCompany();
|
||||||
|
AccountConfig accountConfig = accountConfigService.getAccountConfig(company);
|
||||||
|
Journal journal = accountConfigService.getAutoMiscOpeJournal(accountConfig);
|
||||||
|
Account factorCreditAccount = accountConfigService.getFactorCreditAccount(accountConfig);
|
||||||
|
Account factorDebitAccount = accountConfigService.getFactorDebitAccount(accountConfig);
|
||||||
|
|
||||||
|
if (subrogationRelease.getAccountingDate() == null) {
|
||||||
|
subrogationRelease.setAccountingDate(appBaseService.getTodayDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Invoice invoice : subrogationRelease.getInvoiceSet()) {
|
||||||
|
if (invoice.getCompanyInTaxTotalRemaining().compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isRefund = false;
|
||||||
|
if (invoice.getOperationTypeSelect() == InvoiceRepository.OPERATION_TYPE_CLIENT_REFUND) {
|
||||||
|
isRefund = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate date = subrogationRelease.getAccountingDate();
|
||||||
|
Move move =
|
||||||
|
moveService
|
||||||
|
.getMoveCreateService()
|
||||||
|
.createMove(
|
||||||
|
journal,
|
||||||
|
company,
|
||||||
|
company.getCurrency(),
|
||||||
|
invoice.getPartner(),
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
MoveRepository.TECHNICAL_ORIGIN_AUTOMATIC);
|
||||||
|
MoveLine creditMoveLine, debitMoveLine;
|
||||||
|
|
||||||
|
debitMoveLine =
|
||||||
|
moveService
|
||||||
|
.getMoveLineService()
|
||||||
|
.createMoveLine(
|
||||||
|
move,
|
||||||
|
invoice.getPartner(),
|
||||||
|
factorDebitAccount,
|
||||||
|
invoice.getCompanyInTaxTotalRemaining(),
|
||||||
|
!isRefund,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
1,
|
||||||
|
subrogationRelease.getSequenceNumber(),
|
||||||
|
invoice.getInvoiceId());
|
||||||
|
|
||||||
|
creditMoveLine =
|
||||||
|
moveService
|
||||||
|
.getMoveLineService()
|
||||||
|
.createMoveLine(
|
||||||
|
move,
|
||||||
|
invoice.getPartner(),
|
||||||
|
factorCreditAccount,
|
||||||
|
invoice.getCompanyInTaxTotalRemaining(),
|
||||||
|
isRefund,
|
||||||
|
date,
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
subrogationRelease.getSequenceNumber(),
|
||||||
|
invoice.getInvoiceId());
|
||||||
|
|
||||||
|
move.addMoveLineListItem(debitMoveLine);
|
||||||
|
move.addMoveLineListItem(creditMoveLine);
|
||||||
|
|
||||||
|
move = moveRepository.save(move);
|
||||||
|
moveService.getMoveValidateService().validate(move);
|
||||||
|
|
||||||
|
invoice.setSubrogationRelease(subrogationRelease);
|
||||||
|
invoice.setSubrogationReleaseMove(move);
|
||||||
|
|
||||||
|
subrogationRelease.addMoveListItem(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
subrogationRelease.setStatusSelect(SubrogationReleaseRepository.STATUS_ACCOUNTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void clear(SubrogationRelease subrogationRelease) {
|
||||||
|
|
||||||
|
if (isSubrogationReleaseCompletelyPaid(subrogationRelease)) {
|
||||||
|
|
||||||
|
subrogationRelease.setStatusSelect(SubrogationReleaseRepository.STATUS_CLEARED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSubrogationReleaseCompletelyPaid(SubrogationRelease subrogationRelease) {
|
||||||
|
|
||||||
|
return subrogationRelease
|
||||||
|
.getInvoiceSet()
|
||||||
|
.stream()
|
||||||
|
.filter(p -> p.getAmountRemaining().compareTo(BigDecimal.ZERO) == 1)
|
||||||
|
.count()
|
||||||
|
== 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user