--
This commit is contained in:
232
AGENTS_ARQUITECTURA.md
Normal file
232
AGENTS_ARQUITECTURA.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# AGENTS_ARQUITECTURA.md
|
||||
|
||||
These rules complement `AGENTS.md` and are mandatory whenever the task changes project structure, C# architecture, database access, repositories, services, contracts, models, or application transactions.
|
||||
|
||||
## Project folder rules
|
||||
|
||||
Use this base structure:
|
||||
|
||||
```text
|
||||
SIG.Web/
|
||||
App_Code/
|
||||
Infrastructure/
|
||||
Sql/
|
||||
Repositories/
|
||||
Security/
|
||||
Utilities/
|
||||
Contracts/
|
||||
Models/
|
||||
Services/
|
||||
Styles/
|
||||
Scripts/
|
||||
Metronic/
|
||||
Site.master
|
||||
Site.master.cs
|
||||
Login.aspx
|
||||
Login.aspx.cs
|
||||
Inicio.aspx
|
||||
Inicio.aspx.cs
|
||||
BundleConfig.cs
|
||||
Global.asax
|
||||
Global.asax.cs
|
||||
Web.config
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- The active application uses the ASP.NET Web Site runtime-compilation model.
|
||||
- Shared C# source belongs in the exact special folder `App_Code`.
|
||||
- Pages, master pages, controls, handlers, and `Global.asax` use `CodeFile` or source compiled from `App_Code`; do not introduce new `CodeBehind` dependencies on `SIG.Web.dll`.
|
||||
- Keep third-party and external assemblies in `bin`, but do not build or deploy a project assembly named `SIG.Web.dll`.
|
||||
- Do not place database access directly inside `.aspx.cs`, `.ascx.cs`, or `Site.master.cs`.
|
||||
- Database-related helpers go under `App_Code/Sql` or a clearly named SQL/data folder.
|
||||
- Business access goes through `Contracts` and `Services`.
|
||||
- The active Web Site does not use explicit project compilation entries; C# files under `App_Code` compile automatically at runtime.
|
||||
|
||||
---
|
||||
|
||||
## Contract rules
|
||||
|
||||
Contracts belong in `/Contracts`.
|
||||
|
||||
Current minimum contracts:
|
||||
|
||||
```text
|
||||
Contracts/IAuthContract.cs
|
||||
Contracts/IUserSessionContract.cs
|
||||
Contracts/IMenuContract.cs
|
||||
Contracts/IMasterPageContract.cs
|
||||
```
|
||||
|
||||
Suggested future contracts:
|
||||
|
||||
```text
|
||||
Contracts/IPermissionContract.cs
|
||||
Contracts/INotificationContract.cs
|
||||
Contracts/ICatalogSearchContract.cs
|
||||
Contracts/IAuditContract.cs
|
||||
Contracts/ICurrentCompanyContract.cs
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Pages call contracts, not SQL classes.
|
||||
- Master page calls contracts, not SQL classes.
|
||||
- Login calls contracts, not SQL classes.
|
||||
- Contracts must return models, DTOs, or result objects, not raw `DataTable` unless migrating legacy code.
|
||||
- If legacy `DataTable` is required, isolate it behind a contract and document why.
|
||||
|
||||
---
|
||||
|
||||
## Repository ownership rules
|
||||
|
||||
Repository ownership is determined by the data domain and stored-procedure prefix, not by the page or feature that currently consumes the data.
|
||||
|
||||
- Procedures named `PA_Gral_*` belong behind contracts and repositories under `Contracts/General` and `Repositories/General`.
|
||||
- General catalogs such as states, countries, municipalities, neighborhoods, and postal codes must not be placed in a security, registration, sales, or page-specific repository.
|
||||
- A feature service such as public registration may orchestrate both its feature repository and `IGeneralCatalogRepository`, but it must not move general catalog access into the feature repository.
|
||||
- Apply the same ownership rule to future procedure families: `PA_Sis_*` belongs to security/system infrastructure, `PA_Tra_*` to procedures, `PA_Vta_*` to sales, and so on.
|
||||
|
||||
## Database executor ownership rules
|
||||
|
||||
- `IDbExecutor`, `DbExecutor`, `StoredProcedureCommand`, `IDbCommand`, and direct stored-procedure execution may only be used inside classes under `Repositories` or repository database infrastructure.
|
||||
- Services must not reference or receive `IDbExecutor`, create database commands, execute readers, or call stored procedures directly.
|
||||
- A service that needs persisted data must depend on a repository contract. The concrete repository receives `IDbExecutor` and owns parameter configuration and result mapping.
|
||||
- Keep the `DbExecutor` implementation under `Repositories/Database`; do not place it under `Services` or expose it publicly through `AppServices`.
|
||||
|
||||
---
|
||||
|
||||
## Service rules
|
||||
|
||||
Services belong in `/Services`.
|
||||
|
||||
Current starter services may include:
|
||||
|
||||
```text
|
||||
Services/ContractRegistry.cs
|
||||
Services/DummyAuthContract.cs
|
||||
Services/UserSessionContract.cs
|
||||
Services/DummyMenuContract.cs
|
||||
Services/MasterPageContract.cs
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- `ContractRegistry` may be used as a simple manual dependency resolver for WebForms.
|
||||
- Do not introduce a complex dependency injection framework unless required.
|
||||
- Services may depend on SQL helpers/repositories.
|
||||
- `.aspx.cs` files should be thin and delegate work to services.
|
||||
- Keep dummy services separate from SQL-backed services.
|
||||
- Services own application transactions when one business operation performs one or more repository mutations.
|
||||
- Use `TransactionLogic` inside a `using` block around the repository calls and invoke `Commit()` only after every required repository result succeeds.
|
||||
- Pages and repositories must not create, commit, roll back, or dispose application transactions.
|
||||
- Repositories participate through the ambient `TransactionScope`; connection strings used for transactional work must not set `Enlist=false`.
|
||||
- Select `TransactionScopeOption`, isolation level, and timeout in the service according to the business operation. Use `RequiresNew` or `Suppress` only when that behavior is intentional and documented by the call site.
|
||||
- Do not include slow external operations such as SMTP or HTTP calls inside a database transaction.
|
||||
|
||||
---
|
||||
|
||||
## Model rules
|
||||
|
||||
Models belong in `/Models`.
|
||||
|
||||
Current starter models may include:
|
||||
|
||||
```text
|
||||
Models/AppUser.cs
|
||||
Models/LoginResult.cs
|
||||
Models/MenuItemModel.cs
|
||||
Models/MasterLayoutModel.cs
|
||||
Models/BreadcrumbItem.cs
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Use models to move data between contracts and WebForms pages.
|
||||
- Do not pass anonymous objects across layers.
|
||||
- Do not expose SQL connection classes or `SqlDataReader` from services to pages.
|
||||
- Keep models simple and serializable when possible.
|
||||
|
||||
---
|
||||
|
||||
## Database and SQL structure rules
|
||||
|
||||
All database connection structure must be centralized under `App_Code/Sql` or an equivalent SQL/data folder.
|
||||
|
||||
Current starter SQL structure:
|
||||
|
||||
```text
|
||||
App_Code/Sql/ConnectionNames.cs
|
||||
App_Code/Sql/IConnectionStringProvider.cs
|
||||
App_Code/Sql/WebConfigConnectionStringProvider.cs
|
||||
App_Code/Sql/SqlConnectionFactory.cs
|
||||
App_Code/Sql/SqlQueryExecutor.cs
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Define connection names in one place.
|
||||
- Read connection strings from `Web.config`.
|
||||
- Do not hardcode connection strings in pages, master, controls, or services.
|
||||
- Do not create `SqlConnection` directly in `.aspx.cs`.
|
||||
- Do not create `SqlCommand` directly in `.aspx.cs`.
|
||||
- Use repositories or SQL executor classes behind contracts.
|
||||
- All application database reads and writes must use stored procedures; inline SQL in C# is prohibited.
|
||||
- Access to modules and catalogs is controlled by the menu and page-access layer. Reusable catalog stored procedures must not query `Sis_Usuarios`, restrict execution by `CveRol`, or return access-denied messages for module authorization.
|
||||
- Keep `@CveUsuarioEjecuta` in catalog procedures for the required signature and auditing when applicable, not to authorize access to the module.
|
||||
- Do not invent or add authorization, role, user-client association, ownership, or business-prerequisite validations to any stored procedure unless the user explicitly requests that exact validation. The user prefers to add those validations manually.
|
||||
- Mandatory: read and follow `AGENTS_STORED_PROCEDURES.md` for naming, output parameters, TRY/CATCH, logging, transactions, and physical deletion.
|
||||
- Mandatory: read and follow `AGENTS_DATA_READER_MAPPING.md` for object, list, `DataTable`, and `JArray` result mapping.
|
||||
- Mandatory: read and follow `AGENTS_DATABASE_ERROR_LOGGING.md` for safe parameter logging and reproducible stored-procedure calls.
|
||||
- Mandatory: read and follow `AGENTS_PAGE_STRUCTURE.md` for the `Pages/Modulo/` location of all new WebForms pages.
|
||||
- Mandatory: read and follow `AGENTS_WEBFORMS_PARTIAL_POSTBACKS.md` for the single master form, ScriptManager ownership, UpdatePanel usage, and partial-postback rules.
|
||||
- Mandatory: read and follow `AGENTS_JAVASCRIPT_INITIALIZATION.md` for per-element initialization flags, global event guards, and idempotent control setup after partial postbacks.
|
||||
- Mandatory: read and follow `AGENTS_CATALOG_STRUCTURE.md` for catalog titles, breadcrumbs, actions, filters, indicators, grids, quick-create modals, and detail pages.
|
||||
- Mandatory: read and follow `AGENTS_DOCUMENT_STORAGE.md` for document folders, client access validation, protected file retrieval, and GIS file naming.
|
||||
- Keep stored procedure names centralized.
|
||||
- Repositories must use `CommandType.StoredProcedure` and parameterized inputs/outputs.
|
||||
- Never concatenate raw user input into SQL.
|
||||
- The database default collation and general text columns must use `Modern_Spanish_CS_AS`.
|
||||
- Columns named `Codigo`, beginning with `Codigo`, or containing a real user login identifier such as `NombreUsuario`, `UsuarioPortal`, or `Acum_PortalUsuario` must use `Modern_Spanish_CI_AS`.
|
||||
- `AgenteUsuario` is browser/device metadata, not a login identifier, and must use the general `Modern_Spanish_CS_AS` collation.
|
||||
- Do not use `Modern_Spanish_CS_AI`.
|
||||
|
||||
Recommended Web.config connection string pattern:
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
<add name="DefaultConnection" connectionString="..." providerName="System.Data.SqlClient" />
|
||||
<add name="SecurityConnection" connectionString="..." providerName="System.Data.SqlClient" />
|
||||
<add name="ReportingConnection" connectionString="..." providerName="System.Data.SqlClient" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Base page rules
|
||||
|
||||
Normal pages should inherit from a C# base page.
|
||||
|
||||
Preferred base class:
|
||||
|
||||
```text
|
||||
App_Code/Infrastructure/ClsPaginaBase.cs
|
||||
```
|
||||
|
||||
If the starter currently has `WebFormsPageBase.cs`, either:
|
||||
|
||||
- rename it to `ClsPaginaBase.cs`, or
|
||||
- keep `WebFormsPageBase` and update this AGENTS.md/project rules consistently.
|
||||
|
||||
Do not keep both base classes doing the same job.
|
||||
|
||||
Base page responsibilities:
|
||||
|
||||
- Validate authenticated session.
|
||||
- Expose current user from `IUserSessionContract`.
|
||||
- Provide helper methods for messages, redirects, and permissions.
|
||||
- Avoid database access.
|
||||
- Avoid page-specific business logic.
|
||||
|
||||
---
|
||||
|
||||
153
AGENTS_MANTENIMIENTO_PROYECTO.md
Normal file
153
AGENTS_MANTENIMIENTO_PROYECTO.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# AGENTS_MANTENIMIENTO_PROYECTO.md
|
||||
|
||||
These rules complement `AGENTS.md` and are mandatory whenever the task involves commands, security, error handling, user feedback, grids, PDF migration, file delivery, verification, or project evolution.
|
||||
|
||||
## Command rules
|
||||
|
||||
When giving commands for this project:
|
||||
|
||||
- Prefer **PowerShell**, **Developer PowerShell**, or **Visual Studio Package Manager Console** commands.
|
||||
- Commands must be written in **one line**.
|
||||
- Do not use PowerShell line continuation with backticks.
|
||||
- Do not suggest `dotnet new webforms` because WebForms is not supported by the .NET CLI as an ASP.NET Core project.
|
||||
- If a WebForms project must be created from command line, use Visual Studio/MSBuild-compatible project files or create the project through Visual Studio using **ASP.NET Web Application (.NET Framework)**.
|
||||
- Target framework must be `.NET Framework 4.8` or `.NET Framework 4.8.1`.
|
||||
|
||||
Recommended project creation path:
|
||||
|
||||
```powershell
|
||||
mkdir "C:\Proyectos\Agua de hermosillo\Plataforma de Desarrolladores"
|
||||
```
|
||||
|
||||
```powershell
|
||||
cd "C:\Proyectos\Agua de hermosillo\Plataforma de Desarrolladores"
|
||||
```
|
||||
|
||||
Then create/open the WebForms project in Visual Studio 2022 as:
|
||||
|
||||
```text
|
||||
ASP.NET Web Application (.NET Framework) → Web Forms → C# → .NET Framework 4.8/4.8.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security rules
|
||||
|
||||
- Do not store passwords in code, comments, Web.config examples, or session.
|
||||
- Do not expose real connection strings in committed files.
|
||||
- Use dummy values in examples.
|
||||
- Use parameterized SQL.
|
||||
- Validate uploaded files by extension, MIME type, and size when uploads are later added.
|
||||
- Avoid writing raw exception details to the user in production.
|
||||
- Keep `customErrors mode="Off"` only for local development.
|
||||
|
||||
---
|
||||
|
||||
## Error handling rules
|
||||
|
||||
Controlled outcomes and technical failures must use different logs.
|
||||
|
||||
- `@ErrorTipo = 1`, SQL exceptions, timeouts, contract failures, and unexpected exceptions go to the main technical log.
|
||||
- `@ErrorTipo = 2` is a controlled warning. It must not be written to the main technical log.
|
||||
- Controlled warnings go to daily compact files under `~/log/controlled`.
|
||||
- Controlled log files retain only the current day and the previous two days. The retention is configured with `ControlledLogRetentionDays = 3`.
|
||||
- Explicit controlled throws must use `ControlledApplicationException`; do not classify arbitrary `Exception` or `InvalidOperationException` instances as controlled.
|
||||
- Controlled logs record date, source, procedure, URL, and friendly message, but omit full stack traces and replay SQL to remain compact.
|
||||
- A controlled exception must still return a friendly result to the page and must never be presented as an unexpected application failure.
|
||||
|
||||
- Handle null session user cleanly and redirect to login.
|
||||
- Handle failed login with a friendly message.
|
||||
- Handle async postback errors through `ScriptManager.AsyncPostBackError` only if the handler exists.
|
||||
- Avoid infinite loading states in JavaScript controls.
|
||||
- For AJAX/server search controls, use client and server timeouts.
|
||||
- Recommended default search timeout: about 20 to 30 seconds unless the user asks otherwise.
|
||||
|
||||
## Action availability and feedback rules
|
||||
|
||||
- Do not disable a button or primary action only because a business prerequisite is missing, such as an unassigned client or an empty related catalog.
|
||||
- Keep the action available by default; when the user clicks it, validate the prerequisite and show a clear message explaining why the operation cannot continue and what must be done next.
|
||||
- Never leave a disabled action without an immediately visible explanation.
|
||||
- Before adding `Enabled="false"`, the HTML `disabled` attribute, or an equivalent disabled CSS/JavaScript state to a catalog or page action, ask the user whether disabling is acceptable or whether a message, modal, link, or other alternative should be used.
|
||||
- A transient disabled state used only while a request is being processed to prevent duplicate submissions is allowed, but the action must be restored when processing finishes.
|
||||
|
||||
---
|
||||
|
||||
## Grid display rules
|
||||
|
||||
- Every new or modified `asp:GridView` must declare `GridLines="None"`.
|
||||
- Its `CssClass` must include the exact utility class `Widthall` so the grid uses the full available width.
|
||||
- Do not add `table-bordered` to a GridView. Existing visual classes such as `table`, `table-striped`, and `table-hover` may be retained when appropriate.
|
||||
- Keep GridView declarations and their columns expanded and indented according to the source code readability rules.
|
||||
- Detail-page navigation from a GridView or list must use `asp:HyperLink` or another real link with `NavigateUrl`; do not use `LinkButton`, `RowCommand`, or a postback only to open a detail page.
|
||||
- URL-building variables and helpers must describe the row entity, for example `cveFraccionamiento`, `fraccionamientoDetalleUrl`, or `GetFraccionamientoDetalleUrl`. Avoid generic names such as `id`, `itemUrl`, or `detailUrl` when the entity is known.
|
||||
|
||||
---
|
||||
|
||||
## PDF viewer migration rules
|
||||
|
||||
If the PDF viewer is added to this project later:
|
||||
|
||||
- Implement it in C#.
|
||||
- Prefer `App_Code/SigControls` for server controls.
|
||||
- Do not add VB files.
|
||||
- Do not use `/* */` comments in VB reference files; VB references must remain `.vb.txt` only.
|
||||
- Keep global PDF viewer CSS/JS references in bundles.
|
||||
- Do not register duplicate resources from the control and master at the same time.
|
||||
- Session or temp-folder PDF storage must be explicit and centralized.
|
||||
|
||||
---
|
||||
|
||||
## File delivery rules for this project
|
||||
|
||||
When generating a single downloadable file:
|
||||
|
||||
- If the file is `.js` or `.css` and it is not inside a ZIP, append `.txt` to the filename.
|
||||
- Example: `custom.js.txt`, `styles.css.txt`.
|
||||
- If the file is inside a ZIP, keep the real extension `.js` or `.css`.
|
||||
- For project-level delivery, prefer ZIP files.
|
||||
|
||||
---
|
||||
|
||||
## Current implementation checklist
|
||||
|
||||
When modifying or regenerating the project, verify:
|
||||
|
||||
- [ ] Project targets .NET Framework 4.8 or 4.8.1.
|
||||
- [ ] All new code is C#.
|
||||
- [ ] No active `.vb` files were added.
|
||||
- [ ] `Styles`, `Scripts`, and `Metronic` were copied as-is.
|
||||
- [ ] `BundleConfig.cs` contains only bundles rendered by master/login or required by WebForms AJAX.
|
||||
- [ ] `Site.master` owns the only main form.
|
||||
- [ ] Normal pages use `Site.master`.
|
||||
- [ ] Normal pages do not contain full HTML structure.
|
||||
- [ ] Login is the only standalone full HTML page.
|
||||
- [ ] User/session data comes from `IUserSessionContract`.
|
||||
- [ ] Login uses `IAuthContract`.
|
||||
- [ ] Menu comes from `IMenuContract`.
|
||||
- [ ] Master layout data comes from `IMasterPageContract`.
|
||||
- [ ] SQL connection helpers are centralized under `App_Code/Sql`.
|
||||
- [ ] Pages do not directly instantiate SQL connections.
|
||||
- [ ] Placeholder IDs are `H`, `C`, and `J`.
|
||||
- [ ] No hidden old search box was restored.
|
||||
- [ ] Actions button is preserved when present in the selected layout.
|
||||
- [ ] `Web.config` login URL matches the actual login page filename.
|
||||
- [ ] No duplicate `Login.aspx` / `LogIn.aspx` pages exist.
|
||||
- [ ] No OWIN startup error exists, or OWIN automatic startup is disabled.
|
||||
- [ ] No missing CodeDom provider error exists.
|
||||
|
||||
---
|
||||
|
||||
## Preferred next evolution
|
||||
|
||||
After the starter works, the safest growth path is:
|
||||
|
||||
1. Replace dummy login with SQL-backed `IAuthContract`.
|
||||
2. Replace dummy menu with SQL-backed `IMenuContract`.
|
||||
3. Add permission contract.
|
||||
4. Add base page authorization checks.
|
||||
5. Add reusable controls one by one.
|
||||
6. Add catalog search and UI helpers.
|
||||
7. Add PDF viewer only after the base shell is stable.
|
||||
|
||||
Keep every new feature behind contracts so the WebForms UI remains thin and easier to migrate later if needed.
|
||||
|
||||
415
AGENTS_WEBFORMS_ESTRUCTURA.md
Normal file
415
AGENTS_WEBFORMS_ESTRUCTURA.md
Normal file
@@ -0,0 +1,415 @@
|
||||
# AGENTS_WEBFORMS_ESTRUCTURA.md
|
||||
|
||||
These rules complement `AGENTS.md` and are mandatory whenever the task changes WebForms pages, the master page, login, session behavior, bundles, assets, configuration, controls, or the application shell.
|
||||
|
||||
## Asset folder rules
|
||||
|
||||
The following folders are legacy visual dependencies and must be copied as complete folders:
|
||||
|
||||
```text
|
||||
Styles/
|
||||
Scripts/
|
||||
Metronic/
|
||||
```
|
||||
|
||||
Do not replace Metronic with Bootstrap-only layout.
|
||||
Do not upgrade Metronic unless the user explicitly asks.
|
||||
Do not remove old scripts just because they look unused; only remove references from bundles when they are not used by the master/login flow.
|
||||
|
||||
---
|
||||
|
||||
## Bundle rules
|
||||
|
||||
The project must implement only the bundle methods needed by the current `Site.master` and login page.
|
||||
|
||||
Do not bring every old bundle method from the legacy project.
|
||||
Do not add unused bundle groups just because they existed before.
|
||||
Do not add duplicate bundle keys.
|
||||
Do not add empty bundle methods.
|
||||
|
||||
Allowed current bundle keys are the ones actually rendered by master/login, especially:
|
||||
|
||||
```text
|
||||
~/bundles/modernizr
|
||||
~/bundles/scripts
|
||||
~/bundles/highcharts
|
||||
~/Metronic/assets/global/scripts/JSV1
|
||||
~/Metronic/assets/global/css/cssV1
|
||||
```
|
||||
|
||||
WebForms/AjaxControlToolkit support bundles are allowed only when referenced by `ScriptManager` or required by WebForms controls:
|
||||
|
||||
```text
|
||||
~/bundles/jquery
|
||||
~/bundles/WebFormsJs
|
||||
~/bundles/MsAjaxJs
|
||||
~/Content/AjaxControlToolkit/Styles/Bundle
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- If `Site.master` or `Login.aspx` does not render a bundle, do not add it.
|
||||
- If a bundle exists only for old pages not migrated yet, leave it out until the page needs it.
|
||||
- Prefer preserving original asset paths from `Styles`, `Scripts`, and `Metronic`.
|
||||
- Use `CssRewriteUrlTransform` for CSS bundles that reference fonts, images, or relative URLs.
|
||||
- Do not register CSS/JS from server controls when the style/script is global; use `BundleConfig` and the master page.
|
||||
|
||||
---
|
||||
|
||||
## WebForms page rules
|
||||
|
||||
All normal `.aspx` pages must use `Site.master`, except the login page.
|
||||
|
||||
Normal pages:
|
||||
|
||||
- Must include `MasterPageFile="~/Site.master"`.
|
||||
- Must not include `<html>`, `<head>`, `<body>`, or `<form>`.
|
||||
- Must use `<asp:Content>` controls.
|
||||
- Should inherit from `ClsPaginaBase` or the current C# page base class.
|
||||
- Must not connect directly to SQL classes.
|
||||
- Must call contracts/services for data, authentication, permissions, catalogs, menus, and user context.
|
||||
|
||||
Public registration exception:
|
||||
|
||||
- `Pages/Security/RegistroCliente.aspx`, `RegistroPendiente.aspx` and `VerificarCorreo.aspx` may be standalone public pages with their own `form runat="server"`.
|
||||
- `RegistroCliente.aspx` keeps its two-step draft in encrypted ViewState and persists only after all client/company validations pass.
|
||||
- All persistence continues through contracts/services/repositories and stored procedures.
|
||||
|
||||
Login page:
|
||||
|
||||
- Is the only page allowed to have its own full HTML structure.
|
||||
- May inherit from `System.Web.UI.Page` or its own login base class.
|
||||
- Must not inherit from `ClsPaginaBase` if that base class requires an authenticated session.
|
||||
- Must use `IAuthContract` or the current auth contract.
|
||||
- Must create a dummy session until real authentication is implemented.
|
||||
- Must not hardcode real database login logic in `Login.aspx.cs`.
|
||||
|
||||
Important naming rule:
|
||||
|
||||
- Do not create both `Login.aspx` and `LogIn.aspx`.
|
||||
- If the starter already uses `LogIn.aspx`, keep that name and keep `Web.config` consistent.
|
||||
- If creating from scratch, prefer `Login.aspx`, but update `Web.config`, redirects, and links consistently.
|
||||
|
||||
---
|
||||
|
||||
## Master page rules
|
||||
|
||||
`Site.master` owns the main HTML structure.
|
||||
|
||||
Rules:
|
||||
|
||||
- `Site.master` owns the only main `<form runat="server">`.
|
||||
- `Site.master` must keep the Metronic layout structure.
|
||||
- Keep the sidebar/header/page-content structure similar to the original Metronic project.
|
||||
- Do not restore the hidden search box from the old header.
|
||||
- Keep the actions button if it exists in the selected master layout.
|
||||
- Do not hardcode real user/menu database logic inside `Site.master.cs`.
|
||||
- User data must come from a contract/service.
|
||||
- Menu data must come from a contract/service.
|
||||
- Breadcrumb/title/layout data must come from a contract/service when dynamic.
|
||||
- Do not use `<title id="Titulo" runat="server">`.
|
||||
- Prefer `<title><%: Page.Title %></title>`.
|
||||
- If a generated starter currently uses a title literal, replace it with `Page.Title` unless there is a specific reason to keep the literal.
|
||||
|
||||
Current preferred contracts:
|
||||
|
||||
```text
|
||||
IAuthContract
|
||||
IUserSessionContract
|
||||
IMenuContract
|
||||
IMasterPageContract
|
||||
```
|
||||
|
||||
If old names such as `IUserContextProvider` or `IMenuProvider` exist, migrate them to the current contract naming or create adapters. Do not keep two competing naming systems.
|
||||
|
||||
---
|
||||
|
||||
## ContentPlaceHolder rules
|
||||
|
||||
`Site.master` must use short placeholder IDs.
|
||||
|
||||
Preferred final placeholder IDs:
|
||||
|
||||
```text
|
||||
H = page-specific head/CSS content
|
||||
C = main page content
|
||||
J = page-specific JavaScript
|
||||
```
|
||||
|
||||
Example in `Site.master`:
|
||||
|
||||
```aspx
|
||||
<asp:ContentPlaceHolder ID="H" runat="server" />
|
||||
<asp:ContentPlaceHolder ID="C" runat="server" />
|
||||
<asp:ContentPlaceHolder ID="J" runat="server" />
|
||||
```
|
||||
|
||||
Example in a normal page:
|
||||
|
||||
```aspx
|
||||
<asp:Content ID="ContentHead" ContentPlaceHolderID="H" runat="server">
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ID="ContentMain" ContentPlaceHolderID="C" runat="server">
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ID="ContentScripts" ContentPlaceHolderID="J" runat="server">
|
||||
</asp:Content>
|
||||
```
|
||||
|
||||
If the generated starter currently has `HeadContent`, `MainContent`, or `ScriptsContent`, rename them to `H`, `C`, and `J` before adding more pages.
|
||||
|
||||
Do not mix placeholder naming systems in the same project.
|
||||
|
||||
---
|
||||
|
||||
## WebForms tab and page-state rules
|
||||
|
||||
- Register AjaxControlToolkit once in `Web.config` under `system.web/pages/controls` with the exact prefix `ajax`; do not add `<%@ Register ... %>` directives for it in individual pages.
|
||||
- AjaxControlToolkit controls must use the `ajax:` prefix, for example `ajax:TabContainer` and `ajax:TabPanel`; do not use `ajaxToolkit:` or another page-specific prefix.
|
||||
- Tabs in WebForms pages must use `ajax:TabContainer` and `ajax:TabPanel`; do not build page tabs with Bootstrap `nav-tabs`, custom hidden panels, or JavaScript-only tab switching.
|
||||
- Use the `ScriptManager` owned by `Site.master` and the existing AjaxControlToolkit resources. Do not add another `ScriptManager` or duplicate Toolkit scripts/styles.
|
||||
- Server-side page state such as current entity keys, selected child keys, editing mode, flags, and the active tab must be stored in typed `ViewState` properties when it must survive postback.
|
||||
- Do not add `asp:HiddenField` merely to preserve server-side state across postbacks. A hidden field is allowed only when client-side JavaScript must read or change the value.
|
||||
- Hidden-field values are client-controlled and must never be trusted for authorization or sensitive decisions; validate them again on the server when their use is unavoidable.
|
||||
- Keep ViewState values small and serializable. Do not store database connections, commands, readers, services, repositories, or unnecessarily large result sets in ViewState.
|
||||
- ViewState property and key names must identify the entity and purpose, for example `CveFraccionamientoActual` and `CveFraccionamientoEtapaActual`.
|
||||
- When a postback needs to recover related values from an already loaded catalog, store the typed serializable object list in a typed `ViewState` property and locate the selected object by its key.
|
||||
- Do not copy server-owned catalog or model values into HTML `data-*` attributes, CSS classes, hidden fields, or other client-controlled markup merely to recover them during a postback. Read them from the typed object list stored in `ViewState`.
|
||||
|
||||
---
|
||||
|
||||
## Login and session rules
|
||||
|
||||
Authentication must go through a contract.
|
||||
|
||||
Required flow:
|
||||
|
||||
```text
|
||||
Login.aspx.cs
|
||||
↓
|
||||
IAuthContract
|
||||
↓
|
||||
DummyAuthContract now, real AuthService later
|
||||
↓
|
||||
IUserSessionContract
|
||||
↓
|
||||
Session user
|
||||
```
|
||||
|
||||
Initial login may be dummy.
|
||||
|
||||
Dummy session user should be safe and clearly fake, for example:
|
||||
|
||||
```text
|
||||
UserId: 15
|
||||
CompanyId: 1
|
||||
RoleId: 1
|
||||
RoleName: Administrador
|
||||
CompanyName: Empresa Demo
|
||||
DisplayName: Usuario Demo
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Dummy login may accept any non-empty username and password during starter setup.
|
||||
- Mark dummy authentication clearly in code comments.
|
||||
- Do not mix real SQL authentication with dummy authentication in the same class.
|
||||
- When real login is implemented, create a new service such as `SqlAuthContract` or `AuthService`.
|
||||
- Do not store passwords in session.
|
||||
- Do not log raw passwords.
|
||||
- Use Forms Authentication if staying with classic WebForms auth.
|
||||
|
||||
---
|
||||
|
||||
## Global.asax rules
|
||||
|
||||
`Global.asax` / `Global.asax.cs` should:
|
||||
|
||||
- Register bundles through `BundleConfig.RegisterBundles(BundleTable.Bundles)`.
|
||||
- Configure basic application startup.
|
||||
- Avoid business logic.
|
||||
- Avoid direct database startup queries unless absolutely required.
|
||||
|
||||
If OWIN is not used, prevent startup errors by adding this to `Web.config`:
|
||||
|
||||
```xml
|
||||
<add key="owin:AutomaticAppStartup" value="false" />
|
||||
```
|
||||
|
||||
Do not add OWIN packages unless the project actually needs OWIN.
|
||||
|
||||
---
|
||||
|
||||
## Web.config rules
|
||||
|
||||
`Web.config` must stay compatible with ASP.NET WebForms on .NET Framework 4.8/4.8.1.
|
||||
|
||||
Rules:
|
||||
|
||||
- Use Forms Authentication unless a different auth system is explicitly requested.
|
||||
- Allow anonymous access only to the login page and required static assets.
|
||||
- Do not add ASP.NET Core middleware settings.
|
||||
- Do not add unsupported `.NET Core` config sections.
|
||||
- Do not add CodeDom provider entries unless the matching NuGet package is installed.
|
||||
- If this error appears: `No se pudo ubicar el tipo de proveedor CodeDom Microsoft.CodeDom.Providers.DotNetCompilerPlatform...`, either install the exact package version or remove/fix the `system.codedom` section.
|
||||
- Keep MIME mappings for fonts such as `.woff` and `.woff2` when Metronic requires them.
|
||||
|
||||
---
|
||||
|
||||
## OWIN rule
|
||||
|
||||
If the application shows this error:
|
||||
|
||||
```text
|
||||
No assembly found containing an OwinStartupAttribute
|
||||
```
|
||||
|
||||
And the project does not use OWIN, add this in `appSettings`:
|
||||
|
||||
```xml
|
||||
<add key="owin:AutomaticAppStartup" value="false" />
|
||||
```
|
||||
|
||||
Do not create an empty OWIN startup class just to silence the error unless OWIN is actually required.
|
||||
|
||||
---
|
||||
|
||||
## Site.master rendering rules
|
||||
|
||||
The master page should render bundles and scripts in this general order:
|
||||
|
||||
Inside `<head>`:
|
||||
|
||||
```aspx
|
||||
<%: Scripts.Render("~/bundles/modernizr") %>
|
||||
<%: Styles.Render("~/Content/AjaxControlToolkit/Styles/Bundle") %>
|
||||
<%: Styles.Render("~/Metronic/assets/global/css/cssV1") %>
|
||||
<asp:ContentPlaceHolder ID="H" runat="server" />
|
||||
```
|
||||
|
||||
Inside `<form>` near the top:
|
||||
|
||||
```aspx
|
||||
<asp:ScriptManager ID="TSM" runat="server" />
|
||||
<%: Scripts.Render("~/bundles/scripts") %>
|
||||
```
|
||||
|
||||
Before closing `</form>`:
|
||||
|
||||
```aspx
|
||||
<%: Scripts.Render("~/Metronic/assets/global/scripts/JSV1") %>
|
||||
<%: Scripts.Render("~/bundles/highcharts") %>
|
||||
<asp:ContentPlaceHolder ID="J" runat="server" />
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Do not render the same script twice.
|
||||
- Do not render JQuery twice.
|
||||
- Keep `ScriptManager` if AjaxControlToolkit, UpdatePanel, or WebForms AJAX is used.
|
||||
- Keep `TSM_AsyncPostBackError` only if implemented in code-behind.
|
||||
- Remove or implement any event handler referenced by markup.
|
||||
|
||||
---
|
||||
|
||||
## Header/menu rules
|
||||
|
||||
The master header must preserve the selected Metronic layout.
|
||||
|
||||
Rules:
|
||||
|
||||
- Keep user dropdown.
|
||||
- Keep logout option.
|
||||
- Keep actions button when present.
|
||||
- Do not restore the hidden/old search box from legacy header.
|
||||
- Sidebar menu must be built from `IMenuContract`.
|
||||
- Do not build the menu from SQL inside `Site.master.cs`.
|
||||
- Menu items should use `MenuItemModel` or an equivalent model.
|
||||
- Encode text output when generating HTML menu strings.
|
||||
- Module visibility and page access are separate concerns: `Sis_Modulos.Visible` controls whether an item is shown in the menu, but it must not deny direct page access.
|
||||
- `PA_Sis_PaginaAccessCheck` must validate role assignment, `PuedeVer`, active state, and URL. It must not require `Sis_Modulos.Visible = 1`.
|
||||
|
||||
---
|
||||
|
||||
## Page title and breadcrumb rules
|
||||
|
||||
Page title and breadcrumb should be handled consistently.
|
||||
|
||||
Rules:
|
||||
|
||||
- Use `Page.Title` for the browser title.
|
||||
- Use a master/layout model for visible page title and breadcrumb.
|
||||
- Do not hardcode global breadcrumb logic in every page.
|
||||
- Normal pages may set page title in `Page_Load` or via properties.
|
||||
|
||||
Preferred model:
|
||||
|
||||
```text
|
||||
MasterLayoutModel
|
||||
PageTitle
|
||||
Breadcrumbs
|
||||
CurrentUser
|
||||
MenuItems
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## JavaScript and CSS rules
|
||||
|
||||
- Global scripts/styles must be registered in `BundleConfig` and rendered by master.
|
||||
- Page-specific scripts go in placeholder `J`.
|
||||
- Page-specific CSS/head content goes in placeholder `H`.
|
||||
- Do not inline large JavaScript blocks in `.aspx` unless page-specific and small.
|
||||
- Do not remove existing custom legacy files unless the user asks.
|
||||
- Fix null `addEventListener` errors by checking that the element exists before attaching events.
|
||||
- Avoid blocking Ctrl+V unless a specific feature requires it.
|
||||
|
||||
---
|
||||
|
||||
## User control rules
|
||||
|
||||
If server controls are migrated:
|
||||
|
||||
- Prefer C# classes under `App_Code/SigControls` when creating reusable server controls.
|
||||
- Do not mix WebForms `.ascx` user controls with App_Code server-control classes unless there is a clear reason.
|
||||
- Do not register global CSS/JS from the control when master bundles already include them.
|
||||
- Controls should expose properties/events and avoid direct SQL access.
|
||||
- Controls should call contracts/services when they need data.
|
||||
|
||||
---
|
||||
|
||||
## Home page rules
|
||||
|
||||
Use only one active home page convention.
|
||||
|
||||
For local development, the canonical home URL is:
|
||||
|
||||
```text
|
||||
http://localhost:52706/Inicio.aspx
|
||||
```
|
||||
|
||||
The application root must be equivalent and redirect explicitly to that page:
|
||||
|
||||
```text
|
||||
http://localhost:52706/ -> http://localhost:52706/Inicio.aspx
|
||||
```
|
||||
|
||||
Keep the root redirect and the `Inicio.aspx` default document consistent. Do not introduce another startup page.
|
||||
|
||||
Allowed options:
|
||||
|
||||
```text
|
||||
Default.aspx
|
||||
Inicio.aspx
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Do not keep both as competing entry pages.
|
||||
- If using `Inicio.aspx`, redirect `Default.aspx` to `Inicio.aspx` or update Forms Authentication default URL.
|
||||
- If using `Default.aspx`, keep Web.config and menu links pointing to `Default.aspx`.
|
||||
- The home page must use `Site.master`.
|
||||
|
||||
---
|
||||
|
||||
@@ -175,17 +175,17 @@ BEGIN
|
||||
UM.UnidadMedida AS Unidad,
|
||||
PS.PS AS Descripcion,
|
||||
VD.PrecioUnitario AS ValorUnitario,
|
||||
VD.PrecioUnitario AS PU,
|
||||
VD.Importe AS Total,
|
||||
VD.Descuento,
|
||||
OI.CodigoObjetoImpuesto AS ObjetoImpuesto,
|
||||
CONVERT(
|
||||
decimal(19, 6),
|
||||
ROUND(VD.Cantidad * VD.PrecioUnitario, 6) - VD.Descuento
|
||||
VD.Importe - VD.Descuento
|
||||
) AS BaseIVA,
|
||||
CONVERT(
|
||||
decimal(19, 6),
|
||||
ISNULL(PS.IVA, 0) / 100.0
|
||||
) AS TasaIVA,
|
||||
CONVERT(decimal(19, 6), VD.IVA) AS ImporteIVA
|
||||
CONVERT(decimal(19, 6), 0.16) AS TasaIVA,
|
||||
CONVERT(decimal(19, 6), VD.IVA) AS ImporteIVA,
|
||||
CONVERT(decimal(19, 6), 0.16) AS PorcentajeIVA
|
||||
FROM dbo.VentasDetalle AS VD
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = VD.CvePS
|
||||
|
||||
@@ -579,10 +579,9 @@ BEGIN
|
||||
DECLARE @Total decimal(18, 2);
|
||||
|
||||
SELECT
|
||||
@SubTotal = CONVERT(decimal(18, 2), SUM(ROUND(Cantidad * PrecioUnitario, 2))),
|
||||
@SubTotal = CONVERT(decimal(18, 2), SUM(Importe)),
|
||||
@Descuento = CONVERT(decimal(18, 2), SUM(Descuento)),
|
||||
@IVA = CONVERT(decimal(18, 2), SUM(IVA)),
|
||||
@Total = CONVERT(decimal(18, 2), SUM(Importe))
|
||||
@IVA = CONVERT(decimal(18, 2), SUM(IVA))
|
||||
FROM dbo.VentasDetalle
|
||||
WHERE CveVenta = @CveVenta;
|
||||
|
||||
@@ -592,11 +591,17 @@ BEGIN
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
SET @Descuento = ISNULL(@Descuento, 0);
|
||||
SET @IVA = ISNULL(@IVA, 0);
|
||||
SET @Total = CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(@SubTotal - @Descuento + @IVA, 2));
|
||||
|
||||
UPDATE dbo.Ventas
|
||||
SET
|
||||
SubTotal = @SubTotal,
|
||||
Descuento = ISNULL(@Descuento, 0),
|
||||
IVA = ISNULL(@IVA, 0),
|
||||
Descuento = @Descuento,
|
||||
IVA = @IVA,
|
||||
Total = @Total,
|
||||
CveUsuarioModifico = @CveUsuarioEjecuta
|
||||
WHERE CveVenta = @CveVenta;
|
||||
@@ -738,20 +743,6 @@ BEGIN
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.Vta_Pagos
|
||||
WHERE CveVenta = @CveVenta
|
||||
AND CveSolicitud = @CveSolicitud
|
||||
AND CveTramitePago = @CveTramitePago
|
||||
AND EsActivo = 1
|
||||
)
|
||||
BEGIN
|
||||
SELECT @ErrorMostrar = 'La venta debe estar pagada antes de timbrarla.', @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
IF EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
@@ -817,11 +808,17 @@ BEGIN
|
||||
UM.UnidadMedida AS Unidad,
|
||||
PS.PS AS Descripcion,
|
||||
VD.PrecioUnitario AS ValorUnitario,
|
||||
VD.PrecioUnitario AS PU,
|
||||
VD.Importe AS Total,
|
||||
VD.Descuento,
|
||||
OI.CodigoObjetoImpuesto AS ObjetoImpuesto,
|
||||
CONVERT(decimal(19, 6), ROUND(VD.Cantidad * VD.PrecioUnitario, 6) - VD.Descuento) AS BaseIVA,
|
||||
CONVERT(decimal(19, 6), ISNULL(PS.IVA, 0) / 100.0) AS TasaIVA,
|
||||
CONVERT(decimal(19, 6), VD.IVA) AS ImporteIVA
|
||||
CONVERT(
|
||||
decimal(19, 6),
|
||||
VD.Importe - VD.Descuento
|
||||
) AS BaseIVA,
|
||||
CONVERT(decimal(19, 6), 0.16) AS TasaIVA,
|
||||
CONVERT(decimal(19, 6), VD.IVA) AS ImporteIVA,
|
||||
CONVERT(decimal(19, 6), 0.16) AS PorcentajeIVA
|
||||
FROM dbo.VentasDetalle AS VD
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = VD.CvePS
|
||||
@@ -860,6 +857,7 @@ BEGIN
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE @CveVenta int;
|
||||
DECLARE @PorcentajeIVA decimal(9, 6) = 0.16;
|
||||
|
||||
SELECT @CveVenta = SP.CveVenta
|
||||
FROM dbo.Tra_SolicitudesPagos AS SP
|
||||
@@ -935,11 +933,17 @@ BEGIN
|
||||
ELSE PS.Codigo COLLATE DATABASE_DEFAULT +
|
||||
' - ' + PS.PS COLLATE DATABASE_DEFAULT
|
||||
END AS ProductoServicio,
|
||||
CONVERT(decimal(18, 4), D.Cantidad) AS Cantidad,
|
||||
CONVERT(decimal(18, 2), PS.Precio) AS PrecioUnitario,
|
||||
CONVERT(decimal(18, 4), 1) AS Cantidad,
|
||||
CONVERT(decimal(18, 2), Costo.Importe) AS PrecioUnitario,
|
||||
CONVERT(decimal(18, 2), 0) AS Descuento,
|
||||
CONVERT(decimal(18, 2), ROUND(D.Cantidad * PS.Precio * ISNULL(PS.IVA, 0) / 100, 2)) AS IVA,
|
||||
CONVERT(decimal(18, 2), ROUND(D.Cantidad * PS.Precio, 2) + ROUND(D.Cantidad * PS.Precio * ISNULL(PS.IVA, 0) / 100, 2)) AS Importe
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(Costo.Importe * @PorcentajeIVA, 2)
|
||||
) AS IVA,
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(Costo.Importe, 2)
|
||||
) AS Importe
|
||||
FROM dbo.Tra_Solicitudes AS S
|
||||
INNER JOIN dbo.Tra_Pagos AS P
|
||||
ON P.CveTramitePago = @CveTramitePago
|
||||
@@ -949,6 +953,30 @@ BEGIN
|
||||
ON D.CveTramitePago = P.CveTramitePago
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = D.CvePS
|
||||
CROSS APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
CT.Importe
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite = S.CveTipoTramite
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, GETDATE())
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, GETDATE())
|
||||
)
|
||||
ORDER BY
|
||||
ISNULL(
|
||||
CT.FechaInicioVigencia,
|
||||
CONVERT(date, '19000101')) DESC,
|
||||
CT.CveCostoTramite DESC
|
||||
) AS Costo
|
||||
INNER JOIN dbo.UnidadesMedida AS UM
|
||||
ON UM.CveUnidadMedida = D.CveUM
|
||||
INNER JOIN dbo.Clasificaciones AS C
|
||||
@@ -992,7 +1020,8 @@ BEGIN
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE @CveVenta int;
|
||||
DECLARE @PorcentajeIVA decimal(18, 6);
|
||||
DECLARE @PorcentajeIVA decimal(9, 6) = 0.16;
|
||||
DECLARE @Descuento decimal(18, 2) = 0;
|
||||
DECLARE @IVA decimal(18, 2);
|
||||
DECLARE @Importe decimal(18, 2);
|
||||
|
||||
@@ -1021,19 +1050,43 @@ BEGIN
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
SELECT @PorcentajeIVA = CONVERT(decimal(18, 6), ISNULL(IVA, 0))
|
||||
FROM dbo.ProductosServicios
|
||||
WHERE CvePS = @CvePS
|
||||
AND Estado = 1;
|
||||
|
||||
IF @PorcentajeIVA IS NULL OR @Cantidad <= 0 OR @PrecioUnitario < 0
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.ProductosServicios
|
||||
WHERE CvePS = @CvePS
|
||||
AND Estado = 1
|
||||
)
|
||||
OR @Cantidad <= 0
|
||||
OR @PrecioUnitario < 0
|
||||
BEGIN
|
||||
SELECT @ErrorMostrar = 'Capture un producto activo, cantidad y precio unitario válidos.', @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
SET @IVA = CONVERT(decimal(18, 2), ROUND(@Cantidad * @PrecioUnitario * @PorcentajeIVA / 100, 2));
|
||||
SET @Importe = CONVERT(decimal(18, 2), ROUND(@Cantidad * @PrecioUnitario, 2) + @IVA);
|
||||
IF @CveVentaDetalle IS NOT NULL
|
||||
BEGIN
|
||||
SELECT @Descuento = Descuento
|
||||
FROM dbo.VentasDetalle
|
||||
WHERE CveVentaDetalle = @CveVentaDetalle
|
||||
AND CveVenta = @CveVenta;
|
||||
END;
|
||||
|
||||
SET @Importe = CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(@Cantidad * @PrecioUnitario, 2));
|
||||
|
||||
IF @Descuento > @Importe
|
||||
BEGIN
|
||||
SELECT
|
||||
@ErrorMostrar = 'El descuento del concepto no puede ser mayor que su importe.',
|
||||
@ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
SET @IVA = CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND((@Importe - @Descuento) * @PorcentajeIVA, 2));
|
||||
|
||||
IF @CveVentaDetalle IS NULL
|
||||
BEGIN
|
||||
|
||||
@@ -104,6 +104,8 @@ BEGIN
|
||||
@Return = 0;
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE @PorcentajeIVA decimal(9, 6) = 0.16;
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
@@ -125,16 +127,14 @@ BEGIN
|
||||
COUNT_BIG(*) AS NumeroConceptos,
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio),
|
||||
CONVERT(decimal(18, 4), Costo.Importe),
|
||||
2
|
||||
)
|
||||
) AS SubTotal,
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio) *
|
||||
CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100,
|
||||
CONVERT(decimal(18, 4), Costo.Importe) *
|
||||
@PorcentajeIVA,
|
||||
2
|
||||
)
|
||||
) AS IVA
|
||||
@@ -146,6 +146,30 @@ BEGIN
|
||||
ON D.CveTramitePago = P.CveTramitePago
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = D.CvePS
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
CT.Importe
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite = S.CveTipoTramite
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, GETDATE())
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, GETDATE())
|
||||
)
|
||||
ORDER BY
|
||||
ISNULL(
|
||||
CT.FechaInicioVigencia,
|
||||
CONVERT(date, '19000101')) DESC,
|
||||
CT.CveCostoTramite DESC
|
||||
) AS Costo
|
||||
WHERE S.CveFraccionamiento = @CveFraccionamiento
|
||||
GROUP BY
|
||||
S.CveSolicitud,
|
||||
|
||||
@@ -214,6 +214,8 @@ BEGIN
|
||||
@Return = 0;
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE @PorcentajeIVA decimal(9, 6) = 0.16;
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
@@ -235,16 +237,14 @@ BEGIN
|
||||
COUNT_BIG(*) AS NumeroConceptos,
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio),
|
||||
CONVERT(decimal(18, 4), Costo.Importe),
|
||||
2
|
||||
)
|
||||
) AS SubTotal,
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio) *
|
||||
CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100,
|
||||
CONVERT(decimal(18, 4), Costo.Importe) *
|
||||
@PorcentajeIVA,
|
||||
2
|
||||
)
|
||||
) AS IVA
|
||||
@@ -256,6 +256,30 @@ BEGIN
|
||||
ON D.CveTramitePago = P.CveTramitePago
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = D.CvePS
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
CT.Importe
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite = S.CveTipoTramite
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, GETDATE())
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, GETDATE())
|
||||
)
|
||||
ORDER BY
|
||||
ISNULL(
|
||||
CT.FechaInicioVigencia,
|
||||
CONVERT(date, '19000101')) DESC,
|
||||
CT.CveCostoTramite DESC
|
||||
) AS Costo
|
||||
WHERE S.CveFraccionamiento = @CveFraccionamiento
|
||||
AND NOT EXISTS
|
||||
(
|
||||
@@ -555,6 +579,8 @@ BEGIN
|
||||
@Return = 0;
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE @PorcentajeIVA decimal(9, 6) = 0.16;
|
||||
|
||||
SELECT
|
||||
D.CveTramitePagoDetalle,
|
||||
D.CvePS,
|
||||
@@ -585,29 +611,21 @@ BEGIN
|
||||
' - ' +
|
||||
PS.PS COLLATE DATABASE_DEFAULT
|
||||
END AS ProductoServicio,
|
||||
CONVERT(decimal(18, 4), D.Cantidad) AS Cantidad,
|
||||
CONVERT(decimal(18, 2), PS.Precio) AS PrecioUnitario,
|
||||
CONVERT(decimal(18, 4), 1) AS Cantidad,
|
||||
CONVERT(decimal(18, 2), Costo.Importe) AS PrecioUnitario,
|
||||
CONVERT(decimal(18, 2), 0) AS Descuento,
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio) *
|
||||
CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100,
|
||||
CONVERT(decimal(18, 4), Costo.Importe) *
|
||||
@PorcentajeIVA,
|
||||
2
|
||||
)
|
||||
) AS IVA,
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio),
|
||||
2
|
||||
) +
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio) *
|
||||
CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100,
|
||||
CONVERT(decimal(18, 4), Costo.Importe),
|
||||
2
|
||||
)
|
||||
) AS Importe
|
||||
@@ -620,6 +638,33 @@ BEGIN
|
||||
ON D.CveTramitePago = P.CveTramitePago
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = D.CvePS
|
||||
CROSS APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
CT.Importe
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite =
|
||||
(
|
||||
SELECT S.CveTipoTramite
|
||||
FROM dbo.Tra_Solicitudes AS S
|
||||
WHERE S.CveSolicitud = @CveSolicitud
|
||||
)
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, GETDATE())
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, GETDATE())
|
||||
)
|
||||
ORDER BY
|
||||
ISNULL(CT.FechaInicioVigencia, CONVERT(date, '19000101')) DESC,
|
||||
CT.CveCostoTramite DESC
|
||||
) AS Costo
|
||||
INNER JOIN dbo.UnidadesMedida AS UM
|
||||
ON UM.CveUnidadMedida = D.CveUM
|
||||
INNER JOIN dbo.Clasificaciones AS C
|
||||
@@ -669,12 +714,15 @@ BEGIN
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE
|
||||
@PorcentajeIVA decimal(9, 6) = 0.16,
|
||||
@CveVendedor int = 1,
|
||||
@CveCliente int,
|
||||
@CveSubProyecto int,
|
||||
@CveEstatusFactura int,
|
||||
@CveVenta int,
|
||||
@Folio int,
|
||||
@SubTotal decimal(18, 2),
|
||||
@Descuento decimal(18, 2) = 0,
|
||||
@IVA decimal(18, 2),
|
||||
@Total decimal(18, 2),
|
||||
@Fecha datetime = GETDATE();
|
||||
@@ -698,6 +746,43 @@ BEGIN
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
IF EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.Tra_Solicitudes AS S
|
||||
INNER JOIN dbo.Tra_Pagos AS P
|
||||
ON P.CveTramitePago = @CveTramitePago
|
||||
AND P.CveTipoTramite = S.CveTipoTramite
|
||||
AND P.EsActivo = 1
|
||||
INNER JOIN dbo.Tra_PagosDetalle AS D
|
||||
ON D.CveTramitePago = P.CveTramitePago
|
||||
WHERE S.CveSolicitud = @CveSolicitud
|
||||
AND NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite = S.CveTipoTramite
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, @Fecha)
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, @Fecha)
|
||||
)
|
||||
)
|
||||
)
|
||||
BEGIN
|
||||
SELECT
|
||||
@ErrorMostrar = 'Uno o más conceptos no tienen un costo vigente configurado.',
|
||||
@ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
IF EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
@@ -740,8 +825,7 @@ BEGIN
|
||||
decimal(18, 2),
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio),
|
||||
CONVERT(decimal(18, 4), Costo.Importe),
|
||||
2
|
||||
)
|
||||
)
|
||||
@@ -750,9 +834,8 @@ BEGIN
|
||||
decimal(18, 2),
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio) *
|
||||
CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100,
|
||||
CONVERT(decimal(18, 4), Costo.Importe) *
|
||||
@PorcentajeIVA,
|
||||
2
|
||||
)
|
||||
)
|
||||
@@ -760,6 +843,33 @@ BEGIN
|
||||
FROM dbo.Tra_PagosDetalle AS D
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = D.CvePS
|
||||
CROSS APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
CT.Importe
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite =
|
||||
(
|
||||
SELECT S.CveTipoTramite
|
||||
FROM dbo.Tra_Solicitudes AS S
|
||||
WHERE S.CveSolicitud = @CveSolicitud
|
||||
)
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, @Fecha)
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, @Fecha)
|
||||
)
|
||||
ORDER BY
|
||||
ISNULL(CT.FechaInicioVigencia, CONVERT(date, '19000101')) DESC,
|
||||
CT.CveCostoTramite DESC
|
||||
) AS Costo
|
||||
WHERE D.CveTramitePago = @CveTramitePago;
|
||||
|
||||
IF @SubTotal IS NULL
|
||||
@@ -771,7 +881,7 @@ BEGIN
|
||||
END;
|
||||
|
||||
SET @IVA = ISNULL(@IVA, 0);
|
||||
SET @Total = @SubTotal + @IVA;
|
||||
SET @Total = @SubTotal - @Descuento + @IVA;
|
||||
|
||||
SELECT
|
||||
@Folio = ISNULL(MAX(Folio), 0) + 1
|
||||
@@ -787,10 +897,12 @@ BEGIN
|
||||
Folio,
|
||||
Fecha,
|
||||
CveCliente,
|
||||
CveVendedor,
|
||||
CveMetodoPago,
|
||||
CondicionesPago,
|
||||
FormaPago,
|
||||
SubTotal,
|
||||
Descuento,
|
||||
IVA,
|
||||
Total,
|
||||
Observaciones,
|
||||
@@ -813,10 +925,12 @@ BEGIN
|
||||
@Folio,
|
||||
@Fecha,
|
||||
@CveCliente,
|
||||
@CveVendedor,
|
||||
2,
|
||||
0,
|
||||
99,
|
||||
@SubTotal,
|
||||
@Descuento,
|
||||
@IVA,
|
||||
@Total,
|
||||
ISNULL(@Observaciones, ''),
|
||||
@@ -854,30 +968,22 @@ BEGIN
|
||||
@CveVenta,
|
||||
D.CvePS,
|
||||
@CveSolicitud,
|
||||
NULL,
|
||||
D.Cantidad,
|
||||
CONVERT(decimal(18, 2), PS.Precio),
|
||||
Costo.CveCostoTramite,
|
||||
CONVERT(decimal(18, 4), 1),
|
||||
CONVERT(decimal(18, 2), Costo.Importe),
|
||||
CONVERT(decimal(18, 2), 0),
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio) *
|
||||
CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100,
|
||||
CONVERT(decimal(18, 4), Costo.Importe) *
|
||||
@PorcentajeIVA,
|
||||
2
|
||||
)
|
||||
),
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio),
|
||||
2
|
||||
) +
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), D.Cantidad) *
|
||||
CONVERT(decimal(18, 4), PS.Precio) *
|
||||
CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100,
|
||||
CONVERT(decimal(18, 4), Costo.Importe),
|
||||
2
|
||||
)
|
||||
),
|
||||
@@ -887,6 +993,34 @@ BEGIN
|
||||
FROM dbo.Tra_PagosDetalle AS D
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = D.CvePS
|
||||
CROSS APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
CT.CveCostoTramite,
|
||||
CT.Importe
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite =
|
||||
(
|
||||
SELECT S.CveTipoTramite
|
||||
FROM dbo.Tra_Solicitudes AS S
|
||||
WHERE S.CveSolicitud = @CveSolicitud
|
||||
)
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, @Fecha)
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, @Fecha)
|
||||
)
|
||||
ORDER BY
|
||||
ISNULL(CT.FechaInicioVigencia, CONVERT(date, '19000101')) DESC,
|
||||
CT.CveCostoTramite DESC
|
||||
) AS Costo
|
||||
WHERE D.CveTramitePago = @CveTramitePago;
|
||||
|
||||
INSERT INTO dbo.Tra_SolicitudesPagos
|
||||
|
||||
2824
Impuestos_Costos_Ventas_Tramites_20260901.sql
Normal file
2824
Impuestos_Costos_Ventas_Tramites_20260901.sql
Normal file
File diff suppressed because it is too large
Load Diff
185
PA_Vta_FraccionamientoPagoPendienteList_Actualizar_20260901.sql
Normal file
185
PA_Vta_FraccionamientoPagoPendienteList_Actualizar_20260901.sql
Normal file
@@ -0,0 +1,185 @@
|
||||
CREATE OR ALTER PROCEDURE dbo.PA_Vta_FraccionamientoPagoPendienteList
|
||||
@CveFraccionamiento int,
|
||||
@CveUsuarioEjecuta int,
|
||||
@ErrorMostrar varchar(max) OUTPUT,
|
||||
@ErrorTipo int OUTPUT,
|
||||
@Return bit OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
SELECT
|
||||
@ErrorMostrar = NULL,
|
||||
@ErrorTipo = 0,
|
||||
@Return = 0;
|
||||
|
||||
BEGIN TRY
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.Fraccionamientos
|
||||
WHERE CveFraccionamiento = @CveFraccionamiento
|
||||
)
|
||||
BEGIN
|
||||
SELECT
|
||||
@ErrorMostrar = 'El fraccionamiento solicitado no existe.',
|
||||
@ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
;WITH Conceptos AS
|
||||
(
|
||||
SELECT
|
||||
S.CveSolicitud,
|
||||
P.CveTramitePago,
|
||||
COUNT_BIG(*) AS NumeroConceptos,
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), Costo.Importe),
|
||||
2
|
||||
) * D.Cantidad
|
||||
) AS SubTotal,
|
||||
SUM(
|
||||
ROUND(
|
||||
CONVERT(decimal(18, 4), Costo.Importe)
|
||||
* D.Cantidad
|
||||
* ISNULL(ImpuestoIVA.TasaOCuota, 0),
|
||||
2
|
||||
)
|
||||
) AS IVA
|
||||
FROM dbo.Tra_Solicitudes AS S
|
||||
INNER JOIN dbo.Tra_Pagos AS P
|
||||
ON P.CveTipoTramite = S.CveTipoTramite
|
||||
AND P.EsActivo = 1
|
||||
INNER JOIN dbo.Tra_PagosDetalle AS D
|
||||
ON D.CveTramitePago = P.CveTramitePago
|
||||
INNER JOIN dbo.ProductosServicios AS PS
|
||||
ON PS.CvePS = D.CvePS
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
CT.CveCostoTramite,
|
||||
CT.Importe
|
||||
FROM dbo.Tra_CostosTramite AS CT
|
||||
WHERE CT.CveTipoTramite = S.CveTipoTramite
|
||||
AND CT.CvePS = D.CvePS
|
||||
AND CT.EsActivo = 1
|
||||
AND
|
||||
(
|
||||
CT.FechaInicioVigencia IS NULL
|
||||
OR CT.FechaInicioVigencia <= CONVERT(date, GETDATE())
|
||||
)
|
||||
AND
|
||||
(
|
||||
CT.FechaFinVigencia IS NULL
|
||||
OR CT.FechaFinVigencia >= CONVERT(date, GETDATE())
|
||||
)
|
||||
ORDER BY
|
||||
ISNULL(
|
||||
CT.FechaInicioVigencia,
|
||||
CONVERT(date, '19000101')) DESC,
|
||||
CT.CveCostoTramite DESC
|
||||
) AS Costo
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1) CTI.TasaOCuota
|
||||
FROM dbo.Tra_CostosTramiteImpuestos AS CTI
|
||||
WHERE CTI.CveCostoTramite = Costo.CveCostoTramite
|
||||
AND CTI.EsRetencion = 0
|
||||
AND CTI.Impuesto = '002'
|
||||
AND CTI.TipoFactor = 'Tasa'
|
||||
) AS ImpuestoIVA
|
||||
WHERE S.CveFraccionamiento = @CveFraccionamiento
|
||||
GROUP BY
|
||||
S.CveSolicitud,
|
||||
P.CveTramitePago
|
||||
)
|
||||
SELECT
|
||||
S.CveSolicitud,
|
||||
P.CveTramitePago,
|
||||
SP.CveVenta,
|
||||
CONVERT(
|
||||
bit,
|
||||
CASE
|
||||
WHEN SP.CveSolicitudPago IS NOT NULL
|
||||
AND V.CveVenta IS NOT NULL THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) AS VentaGenerada,
|
||||
S.Folio AS FolioSolicitud,
|
||||
E.Etapa,
|
||||
TT.TipoTramite,
|
||||
P.Nombre AS NombrePago,
|
||||
CONVERT(int, C.NumeroConceptos) AS NumeroConceptos,
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
CASE
|
||||
WHEN V.CveVenta IS NULL THEN C.SubTotal
|
||||
ELSE V.SubTotal
|
||||
END
|
||||
) AS SubTotal,
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
CASE
|
||||
WHEN V.CveVenta IS NULL THEN C.IVA
|
||||
ELSE V.IVA
|
||||
END
|
||||
) AS IVA,
|
||||
CONVERT(
|
||||
decimal(18, 2),
|
||||
CASE
|
||||
WHEN V.CveVenta IS NULL THEN C.SubTotal + C.IVA
|
||||
ELSE V.Total
|
||||
END
|
||||
) AS Total
|
||||
FROM Conceptos AS C
|
||||
INNER JOIN dbo.Tra_Solicitudes AS S
|
||||
ON S.CveSolicitud = C.CveSolicitud
|
||||
INNER JOIN dbo.FraccionamientosEtapas AS E
|
||||
ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa
|
||||
INNER JOIN dbo.Tra_TiposTramite AS TT
|
||||
ON TT.CveTipoTramite = S.CveTipoTramite
|
||||
INNER JOIN dbo.Tra_Pagos AS P
|
||||
ON P.CveTramitePago = C.CveTramitePago
|
||||
LEFT JOIN dbo.Tra_SolicitudesPagos AS SP
|
||||
ON SP.CveSolicitud = S.CveSolicitud
|
||||
AND SP.CveTramitePago = P.CveTramitePago
|
||||
LEFT JOIN dbo.Ventas AS V
|
||||
ON V.CveVenta = SP.CveVenta
|
||||
WHERE NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.Vta_Pagos AS VP
|
||||
WHERE VP.CveSolicitud = S.CveSolicitud
|
||||
AND VP.CveTramitePago = P.CveTramitePago
|
||||
AND VP.CveVenta = SP.CveVenta
|
||||
AND VP.EsActivo = 1
|
||||
)
|
||||
ORDER BY
|
||||
E.Orden,
|
||||
S.CveSolicitud,
|
||||
P.Orden,
|
||||
P.CveTramitePago;
|
||||
|
||||
SET @Return = 1;
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
SELECT
|
||||
@ErrorMostrar = 'Ocurrió un error al consultar los pagos pendientes; favor de contactar a Sistemas.',
|
||||
@ErrorTipo = 1,
|
||||
@Return = 0;
|
||||
|
||||
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
|
||||
'Número: ', ERROR_NUMBER(),
|
||||
'; Procedimiento: ', COALESCE(
|
||||
ERROR_PROCEDURE(),
|
||||
'PA_Vta_FraccionamientoPagoPendienteList'
|
||||
),
|
||||
'; Línea: ', ERROR_LINE(),
|
||||
'; Detalle: ', ERROR_MESSAGE()
|
||||
);
|
||||
|
||||
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
|
||||
END CATCH;
|
||||
END;
|
||||
GO
|
||||
144
SIG.Web/App_Code/Handlers/Facturacion/DescargaXmlCfdi.cs
Normal file
144
SIG.Web/App_Code/Handlers/Facturacion/DescargaXmlCfdi.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Web.SessionState;
|
||||
using SIG.Web.AppCode.Configuration;
|
||||
using SIG.Web.AppCode.Models.Common;
|
||||
using SIG.Web.AppCode.Models.Facturacion;
|
||||
using SIG.Web.AppCode.Session;
|
||||
|
||||
namespace SIG.Web.Pages.Facturacion
|
||||
{
|
||||
public sealed class DescargaXmlCfdi
|
||||
: IHttpHandler, IRequiresSessionState
|
||||
{
|
||||
public bool IsReusable
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void ProcessRequest(HttpContext contexto)
|
||||
{
|
||||
UserSessionModel usuarioActual = ObtenerUsuarioActual();
|
||||
|
||||
if (usuarioActual == null)
|
||||
{
|
||||
EscribirError(
|
||||
contexto,
|
||||
401,
|
||||
"Su sesión no está disponible. Inicie sesión nuevamente.");
|
||||
return;
|
||||
}
|
||||
|
||||
long cveCfdiDocumento;
|
||||
|
||||
if (!IntentarLeerEnteroLargo(
|
||||
contexto.Request.QueryString["documento"],
|
||||
out cveCfdiDocumento))
|
||||
{
|
||||
EscribirError(
|
||||
contexto,
|
||||
400,
|
||||
"El documento CFDI solicitado no es válido.");
|
||||
return;
|
||||
}
|
||||
|
||||
DbResult<ModeloArchivoCfdi> resultado =
|
||||
AppServices.ServicioTimbradoCfdi.ObtenerXml(
|
||||
cveCfdiDocumento,
|
||||
false,
|
||||
usuarioActual.CveUsuario,
|
||||
usuarioActual.NombreDominio);
|
||||
|
||||
if (!resultado.Success ||
|
||||
resultado.Data == null ||
|
||||
resultado.Data.Contenido == null ||
|
||||
resultado.Data.Contenido.Length == 0)
|
||||
{
|
||||
EscribirError(
|
||||
contexto,
|
||||
404,
|
||||
resultado == null ||
|
||||
string.IsNullOrWhiteSpace(resultado.UserMessage)
|
||||
? "No se encontró el XML sin timbrar."
|
||||
: resultado.UserMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
ModeloArchivoCfdi archivo = resultado.Data;
|
||||
byte[] contenido = archivo.Contenido;
|
||||
|
||||
contexto.Response.Clear();
|
||||
contexto.Response.ClearHeaders();
|
||||
contexto.Response.TrySkipIisCustomErrors = true;
|
||||
contexto.Response.Cache.SetCacheability(HttpCacheability.NoCache);
|
||||
contexto.Response.Cache.SetNoStore();
|
||||
contexto.Response.ContentType =
|
||||
string.IsNullOrWhiteSpace(archivo.TipoContenido)
|
||||
? "application/xml"
|
||||
: archivo.TipoContenido;
|
||||
contexto.Response.AddHeader(
|
||||
"Content-Disposition",
|
||||
"attachment; filename=\"" +
|
||||
SanitizarNombreArchivo(archivo.NombreArchivo) +
|
||||
"\"");
|
||||
contexto.Response.AddHeader(
|
||||
"Content-Length",
|
||||
contenido.Length.ToString(CultureInfo.InvariantCulture));
|
||||
contexto.Response.OutputStream.Write(
|
||||
contenido,
|
||||
0,
|
||||
contenido.Length);
|
||||
contexto.ApplicationInstance.CompleteRequest();
|
||||
}
|
||||
|
||||
private static UserSessionModel ObtenerUsuarioActual()
|
||||
{
|
||||
return AppServices.UserContext != null &&
|
||||
AppServices.UserContext.IsAuthenticated()
|
||||
? AppServices.UserContext.GetCurrentUser()
|
||||
: null;
|
||||
}
|
||||
|
||||
private static bool IntentarLeerEnteroLargo(
|
||||
string valor,
|
||||
out long resultado)
|
||||
{
|
||||
return long.TryParse(
|
||||
valor,
|
||||
NumberStyles.Integer,
|
||||
CultureInfo.InvariantCulture,
|
||||
out resultado) &&
|
||||
resultado > 0;
|
||||
}
|
||||
|
||||
private static string SanitizarNombreArchivo(string nombreArchivo)
|
||||
{
|
||||
string nombre = Path.GetFileName(
|
||||
string.IsNullOrWhiteSpace(nombreArchivo)
|
||||
? "CFDI-SinTimbrar.xml"
|
||||
: nombreArchivo);
|
||||
|
||||
return nombre
|
||||
.Replace("\"", string.Empty)
|
||||
.Replace("\r", string.Empty)
|
||||
.Replace("\n", string.Empty);
|
||||
}
|
||||
|
||||
private static void EscribirError(
|
||||
HttpContext contexto,
|
||||
int codigoEstado,
|
||||
string mensaje)
|
||||
{
|
||||
contexto.Response.Clear();
|
||||
contexto.Response.TrySkipIisCustomErrors = true;
|
||||
contexto.Response.StatusCode = codigoEstado;
|
||||
contexto.Response.ContentType = "text/plain";
|
||||
contexto.Response.ContentEncoding =
|
||||
System.Text.Encoding.UTF8;
|
||||
contexto.Response.Write(mensaje);
|
||||
contexto.ApplicationInstance.CompleteRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,11 @@ namespace SIG.Web.AppCode.Models.General
|
||||
public int CveUnidadMedida { get; set; }
|
||||
public string UnidadMedida { get; set; }
|
||||
public decimal Precio { get; set; }
|
||||
public byte CveObjetoImpuesto { get; set; }
|
||||
public string ObjetoImpuesto { get; set; }
|
||||
public string CodigoObjetoImpuesto { get; set; }
|
||||
public decimal? IVA { get; set; }
|
||||
public string TratamientoIVA { get; set; }
|
||||
public bool EsActivo { get; set; }
|
||||
}
|
||||
|
||||
@@ -24,6 +29,7 @@ namespace SIG.Web.AppCode.Models.General
|
||||
{
|
||||
Clasificaciones = new List<ModeloOpcionClasificacionProducto>();
|
||||
UnidadesMedida = new List<ModeloOpcionUnidadMedida>();
|
||||
ObjetosImpuesto = new List<ModeloOpcionObjetoImpuesto>();
|
||||
}
|
||||
|
||||
public List<ModeloOpcionClasificacionProducto> Clasificaciones
|
||||
@@ -37,6 +43,12 @@ namespace SIG.Web.AppCode.Models.General
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<ModeloOpcionObjetoImpuesto> ObjetosImpuesto
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ModeloOpcionClasificacionProducto
|
||||
@@ -50,4 +62,10 @@ namespace SIG.Web.AppCode.Models.General
|
||||
public int CveUnidadMedida { get; set; }
|
||||
public string UnidadMedida { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ModeloOpcionObjetoImpuesto
|
||||
{
|
||||
public byte CveObjetoImpuesto { get; set; }
|
||||
public string ObjetoImpuesto { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,15 @@ namespace SIG.Web.AppCode.Models.Tramites
|
||||
public string UnidadMedida { get; set; }
|
||||
public string Abreviatura { get; set; }
|
||||
public decimal Cantidad { get; set; }
|
||||
public decimal Precio { get; set; }
|
||||
public decimal PrecioProducto { get; set; }
|
||||
public decimal Importe { get; set; }
|
||||
public byte CveObjetoImpuesto { get; set; }
|
||||
public string CodigoObjetoImpuesto { get; set; }
|
||||
public string ObjetoImpuesto { get; set; }
|
||||
public decimal PorcentajeIVA { get; set; }
|
||||
public decimal ImporteIVA { get; set; }
|
||||
public DateTime? FechaInicioVigencia { get; set; }
|
||||
public DateTime? FechaFinVigencia { get; set; }
|
||||
public decimal Total { get; set; }
|
||||
|
||||
public string UnidadMedidaTexto
|
||||
@@ -154,6 +162,9 @@ namespace SIG.Web.AppCode.Models.Tramites
|
||||
public string UnidadMedida { get; set; }
|
||||
public string Abreviatura { get; set; }
|
||||
public decimal Precio { get; set; }
|
||||
public byte CveObjetoImpuesto { get; set; }
|
||||
public string CodigoObjetoImpuesto { get; set; }
|
||||
public decimal PorcentajeIVA { get; set; }
|
||||
public bool EsActivo { get; set; }
|
||||
|
||||
public string ProductoDisplay
|
||||
|
||||
@@ -129,6 +129,12 @@ namespace SIG.Web.AppCode.Models.Ventas
|
||||
|
||||
public sealed class ModeloConceptoCfdiVentaTramite
|
||||
{
|
||||
public ModeloConceptoCfdiVentaTramite()
|
||||
{
|
||||
Impuestos = new List<ModeloImpuestoCfdiVentaTramite>();
|
||||
}
|
||||
|
||||
public int CveVentaDetalle { get; set; }
|
||||
public string ClaveProductoServicio { get; set; }
|
||||
public string NumeroIdentificacion { get; set; }
|
||||
public decimal Cantidad { get; set; }
|
||||
@@ -141,6 +147,18 @@ namespace SIG.Web.AppCode.Models.Ventas
|
||||
public decimal BaseIVA { get; set; }
|
||||
public decimal TasaIVA { get; set; }
|
||||
public decimal ImporteIVA { get; set; }
|
||||
public List<ModeloImpuestoCfdiVentaTramite> Impuestos { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ModeloImpuestoCfdiVentaTramite
|
||||
{
|
||||
public int CveVentaDetalle { get; set; }
|
||||
public bool EsRetencion { get; set; }
|
||||
public decimal Base { get; set; }
|
||||
public string Impuesto { get; set; }
|
||||
public string TipoFactor { get; set; }
|
||||
public decimal? TasaOCuota { get; set; }
|
||||
public decimal Importe { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ModeloTimbradoVentaTramite
|
||||
|
||||
@@ -87,6 +87,12 @@ namespace SIG.Web.AppCode.Repositories.General
|
||||
lector.ToList<ModeloOpcionUnidadMedida>();
|
||||
}
|
||||
|
||||
if (lector.NextResult())
|
||||
{
|
||||
opciones.ObjetosImpuesto =
|
||||
lector.ToList<ModeloOpcionObjetoImpuesto>();
|
||||
}
|
||||
|
||||
return opciones;
|
||||
});
|
||||
}
|
||||
@@ -135,6 +141,16 @@ namespace SIG.Web.AppCode.Repositories.General
|
||||
"@Precio",
|
||||
productoServicio.Precio,
|
||||
DbType.Decimal);
|
||||
Agregar(
|
||||
comando,
|
||||
"@CveObjetoImpuesto",
|
||||
productoServicio.CveObjetoImpuesto,
|
||||
DbType.Byte);
|
||||
Agregar(
|
||||
comando,
|
||||
"@IVA",
|
||||
productoServicio.IVA,
|
||||
DbType.Decimal);
|
||||
Agregar(
|
||||
comando,
|
||||
"@EsActivo",
|
||||
|
||||
@@ -306,6 +306,18 @@ namespace SIG.Web.AppCode.Repositories.Tramites
|
||||
Add(command, "@CvePS", model.CvePS, DbType.Int32);
|
||||
Add(command, "@CveUM", model.CveUM, DbType.Int32);
|
||||
Add(command, "@Cantidad", model.Cantidad, DbType.Decimal);
|
||||
Add(command, "@Importe", model.Importe, DbType.Decimal);
|
||||
Add(
|
||||
command,
|
||||
"@CveObjetoImpuesto",
|
||||
model.CveObjetoImpuesto,
|
||||
DbType.Byte);
|
||||
Add(
|
||||
command,
|
||||
"@PorcentajeIVA",
|
||||
model.PorcentajeIVA,
|
||||
DbType.Decimal);
|
||||
Add(command, "@FechaInicioVigencia", model.FechaInicioVigencia, DbType.Date);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -361,6 +361,34 @@ namespace SIG.Web.AppCode.Repositories.Ventas
|
||||
lector.ToList<ModeloConceptoCfdiVentaTramite>();
|
||||
}
|
||||
|
||||
if (datos != null && lector.NextResult())
|
||||
{
|
||||
List<ModeloImpuestoCfdiVentaTramite> impuestos =
|
||||
lector.ToList<ModeloImpuestoCfdiVentaTramite>();
|
||||
var conceptosPorDetalle =
|
||||
new Dictionary<int, ModeloConceptoCfdiVentaTramite>();
|
||||
|
||||
foreach (ModeloConceptoCfdiVentaTramite concepto
|
||||
in datos.Conceptos)
|
||||
{
|
||||
conceptosPorDetalle[concepto.CveVentaDetalle] =
|
||||
concepto;
|
||||
}
|
||||
|
||||
foreach (ModeloImpuestoCfdiVentaTramite impuesto
|
||||
in impuestos)
|
||||
{
|
||||
ModeloConceptoCfdiVentaTramite concepto;
|
||||
|
||||
if (conceptosPorDetalle.TryGetValue(
|
||||
impuesto.CveVentaDetalle,
|
||||
out concepto))
|
||||
{
|
||||
concepto.Impuestos.Add(impuesto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return datos;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -138,7 +138,8 @@ namespace SIG.Web.AppCode.Services.Facturacion
|
||||
if (solicitud.TipoCambio.HasValue)
|
||||
{
|
||||
comprobante.TipoCambio =
|
||||
solicitud.TipoCambio.Value;
|
||||
NormalizarTipoCambio(
|
||||
solicitud.TipoCambio.Value);
|
||||
comprobante.TipoCambioSpecified = true;
|
||||
}
|
||||
|
||||
@@ -260,7 +261,8 @@ namespace SIG.Web.AppCode.Services.Facturacion
|
||||
|
||||
if (!EsExento(impuesto.TipoFactor))
|
||||
{
|
||||
resultado.Importe = impuesto.Importe;
|
||||
resultado.Importe =
|
||||
RedondearMoneda(impuesto.Importe);
|
||||
resultado.ImporteSpecified = true;
|
||||
}
|
||||
|
||||
@@ -325,7 +327,9 @@ namespace SIG.Web.AppCode.Services.Facturacion
|
||||
var traslado =
|
||||
new ComprobanteImpuestosTraslado
|
||||
{
|
||||
Base = grupo.Sum(elemento => elemento.Base),
|
||||
Base = RedondearMoneda(
|
||||
grupo.Sum(
|
||||
elemento => elemento.Base)),
|
||||
Impuesto = grupo.Key.Impuesto,
|
||||
TipoFactor = grupo.Key.TipoFactor
|
||||
};
|
||||
@@ -340,7 +344,9 @@ namespace SIG.Web.AppCode.Services.Facturacion
|
||||
if (!EsExento(grupo.Key.TipoFactor))
|
||||
{
|
||||
traslado.Importe =
|
||||
grupo.Sum(elemento => elemento.Importe);
|
||||
RedondearMoneda(
|
||||
grupo.Sum(
|
||||
elemento => elemento.Importe));
|
||||
traslado.ImporteSpecified = true;
|
||||
}
|
||||
|
||||
@@ -605,6 +611,17 @@ namespace SIG.Web.AppCode.Services.Facturacion
|
||||
MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
private static decimal NormalizarTipoCambio(decimal tipoCambio)
|
||||
{
|
||||
string valorNormalizado = tipoCambio.ToString(
|
||||
"0.######",
|
||||
System.Globalization.CultureInfo.InvariantCulture);
|
||||
|
||||
return decimal.Parse(
|
||||
valorNormalizado,
|
||||
System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private static string TextoOpcional(string valor)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(valor)
|
||||
|
||||
@@ -92,6 +92,16 @@ namespace SIG.Web.AppCode.Services.General
|
||||
"Precio",
|
||||
ObtenerValor(anterior, elemento => elemento.Precio),
|
||||
actual.Precio),
|
||||
CrearCampo(
|
||||
"CveObjetoImpuesto",
|
||||
ObtenerValor(
|
||||
anterior,
|
||||
elemento => elemento.CveObjetoImpuesto),
|
||||
actual.CveObjetoImpuesto),
|
||||
CrearCampo(
|
||||
"IVA",
|
||||
ObtenerValor(anterior, elemento => elemento.IVA),
|
||||
actual.IVA),
|
||||
CrearCampo(
|
||||
"Estado",
|
||||
ObtenerValor(anterior, elemento => elemento.EsActivo),
|
||||
|
||||
@@ -238,6 +238,20 @@ namespace SIG.Web.AppCode.Services.General
|
||||
return Fallar<int>("El precio no puede ser negativo.");
|
||||
}
|
||||
|
||||
if (productoServicio.CveObjetoImpuesto <= 0)
|
||||
{
|
||||
return Fallar<int>(
|
||||
"Seleccione el objeto de impuesto del producto o servicio.");
|
||||
}
|
||||
|
||||
if (productoServicio.IVA.HasValue &&
|
||||
productoServicio.IVA.Value != -1m &&
|
||||
productoServicio.IVA.Value != 0m)
|
||||
{
|
||||
return Fallar<int>(
|
||||
"Seleccione IVA general o sin IVA.");
|
||||
}
|
||||
|
||||
return DbResult<int>.Ok(productoServicio.CvePS);
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,15 @@ namespace SIG.Web.AppCode.Services.Tramites
|
||||
Field("CveTramitePago", Value(anterior, item => item.CveTramitePago), actual.CveTramitePago),
|
||||
Field("CvePS", Value(anterior, item => item.CvePS), actual.CvePS),
|
||||
Field("CveUM", Value(anterior, item => item.CveUM), actual.CveUM),
|
||||
Field("Cantidad", Value(anterior, item => item.Cantidad), actual.Cantidad)));
|
||||
Field("Cantidad", Value(anterior, item => item.Cantidad), actual.Cantidad),
|
||||
Field(
|
||||
"CveObjetoImpuesto",
|
||||
Value(anterior, item => item.CveObjetoImpuesto),
|
||||
actual.CveObjetoImpuesto),
|
||||
Field(
|
||||
"PorcentajeIVA",
|
||||
Value(anterior, item => item.PorcentajeIVA),
|
||||
actual.PorcentajeIVA)));
|
||||
|
||||
evento.Relaciones.Add(Relation(
|
||||
"Tra_Pagos",
|
||||
|
||||
@@ -329,10 +329,15 @@ namespace SIG.Web.AppCode.Services.Tramites
|
||||
model.CveTramitePago <= 0 ||
|
||||
model.CvePS <= 0 ||
|
||||
model.CveUM <= 0 ||
|
||||
model.Cantidad <= 0)
|
||||
model.Cantidad <= 0 ||
|
||||
model.Importe < 0 ||
|
||||
model.CveObjetoImpuesto <= 0 ||
|
||||
model.PorcentajeIVA < 0 ||
|
||||
model.PorcentajeIVA > 1 ||
|
||||
!model.FechaInicioVigencia.HasValue)
|
||||
{
|
||||
return Fail<int>(
|
||||
"Seleccione el producto o servicio, la unidad de medida y capture una cantidad mayor que cero.");
|
||||
"Seleccione el producto o servicio, la unidad de medida, el objeto de impuesto y capture una cantidad, un importe, un IVA y una fecha de inicio de vigencia válidos.");
|
||||
}
|
||||
|
||||
return Save(
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><cfdi:Comprobante xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Moneda="MXN" TipoCambio="1" Total="2000.00" xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd" Exportacion="01" MetodoPago="PPD" TipoDeComprobante="I" SubTotal="2000.00" Sello="s24IV21tMl2+E6eeDSq9FEaNF8sA2AaPX3bmjafU76ItSVn8ojWP4c5+9uJIJ1y0q03K7GcBo53xQ/5cSmpP9x9LggAo6jQyMnNiMS9CJUQ4LXUajJMnUyzyIJiIrfZst+cfauBsxzL+nv1cnRmDp+47VHJ14oegYXKlF+avb3HhBz63dBjSHa0x1J84+v/e8h7HoO1zdOOwGjOuhXFn93Ok+rgBiFoZhuLMUGw5zphRsf0DtzqpG1TCwIGAp7YyAZTDN27+icgkl0NzJrRrhIqTzaMx2Q+rTdzSPTjLsYGEtKIdzDcD/DDdZ/TB/3ANXVr5/gFcYNebVi+oMSmS6w==" Certificado="MIIFsDCCA5igAwIBAgIUMzAwMDEwMDAwMDA1MDAwMDM0MTYwDQYJKoZIhvcNAQELBQAwggErMQ8wDQYDVQQDDAZBQyBVQVQxLjAsBgNVBAoMJVNFUlZJQ0lPIERFIEFETUlOSVNUUkFDSU9OIFRSSUJVVEFSSUExGjAYBgNVBAsMEVNBVC1JRVMgQXV0aG9yaXR5MSgwJgYJKoZIhvcNAQkBFhlvc2Nhci5tYXJ0aW5lekBzYXQuZ29iLm14MR0wGwYDVQQJDBQzcmEgY2VycmFkYSBkZSBjYWxpejEOMAwGA1UEEQwFMDYzNzAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBDSVVEQUQgREUgTUVYSUNPMREwDwYDVQQHDAhDT1lPQUNBTjERMA8GA1UELRMIMi41LjQuNDUxJTAjBgkqhkiG9w0BCQITFnJlc3BvbnNhYmxlOiBBQ0RNQS1TQVQwHhcNMjMwNTE4MTE0MzUxWhcNMjcwNTE4MTE0MzUxWjCB1zEnMCUGA1UEAxMeRVNDVUVMQSBLRU1QRVIgVVJHQVRFIFNBIERFIENWMScwJQYDVQQpEx5FU0NVRUxBIEtFTVBFUiBVUkdBVEUgU0EgREUgQ1YxJzAlBgNVBAoTHkVTQ1VFTEEgS0VNUEVSIFVSR0FURSBTQSBERSBDVjElMCMGA1UELRMcRUtVOTAwMzE3M0M5IC8gVkFEQTgwMDkyN0RKMzEeMBwGA1UEBRMVIC8gVkFEQTgwMDkyN0hTUlNSTDA1MRMwEQYDVQQLEwpTdWN1cnNhbCAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtmecO6n2GS0zL025gbHGQVxznPDICoXzR2uUngz4DqxVUC/w9cE6FxSiXm2ap8Gcjg7wmcZfm85EBaxCx/0J2u5CqnhzIoGCdhBPuhWQnIh5TLgj/X6uNquwZkKChbNe9aeFirU/JbyN7Egia9oKH9KZUsodiM/pWAH00PCtoKJ9OBcSHMq8Rqa3KKoBcfkg1ZrgueffwRLws9yOcRWLb02sDOPzGIm/jEFicVYt2Hw1qdRE5xmTZ7AGG0UHs+unkGjpCVeJ+BEBn0JPLWVvDKHZAQMj6s5Bku35+d/MyATkpOPsGT/VTnsouxekDfikJD1f7A1ZpJbqDpkJnss3vQIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQsFAAOCAgEAFaUgj5PqgvJigNMgtrdXZnbPfVBbukAbW4OGnUhNrA7SRAAfv2BSGk16PI0nBOr7qF2mItmBnjgEwk+DTv8Zr7w5qp7vleC6dIsZFNJoa6ZndrE/f7KO1CYruLXr5gwEkIyGfJ9NwyIagvHHMszzyHiSZIA850fWtbqtythpAliJ2jF35M5pNS+YTkRB+T6L/c6m00ymN3q9lT1rB03YywxrLreRSFZOSrbwWfg34EJbHfbFXpCSVYdJRfiVdvHnewN0r5fUlPtR9stQHyuqewzdkyb5jTTw02D2cUfL57vlPStBj7SEi3uOWvLrsiDnnCIxRMYJ2UA2ktDKHk+zWnsDmaeleSzonv2CHW42yXYPCvWi88oE1DJNYLNkIjua7MxAnkNZbScNw01A6zbLsZ3y8G6eEYnxSTRfwjd8EP4kdiHNJftm7Z4iRU7HOVh79/lRWB+gd171s3d/mI9kte3MRy6V8MMEMCAnMboGpaooYwgAmwclI2XZCczNWXfhaWe0ZS5PmytD/GDpXzkX0oEgY9K/uYo5V77NdZbGAjmyi8cE2B2ogvyaN2XfIInrZPgEffJ4AB7kFA2mwesdLOCh0BLD9itmCve3A1FGR4+stO2ANUoiI3w3Tv2yQSg4bjeDlJ08lXaaFCLW2peEXMXjQUk7fmpb5MNuOUTW6BE=" NoCertificado="30001000000500003416" FormaPago="99" LugarExpedicion="42501" Fecha="2026-09-01T16:44:07" Folio="1" Serie="TRA" Version="4.0" xmlns:cfdi="http://www.sat.gob.mx/cfd/4"><cfdi:Emisor Rfc="EKU9003173C9" Nombre="ESCUELA KEMPER URGATE" RegimenFiscal="601" /><cfdi:Receptor Rfc="EKU9003173C9" Nombre="ESCUELA KEMPER URGATE" DomicilioFiscalReceptor="42501" RegimenFiscalReceptor="601" UsoCFDI="G03" /><cfdi:Conceptos><cfdi:Concepto ClaveProdServ="83101500" NoIdentificacion="00001" Cantidad="1.0000" ClaveUnidad="MTQ" Unidad="NO APLICA" Descripcion="Pago adelantado de derechos y aportaciones" ValorUnitario="2000.00" Importe="2000.000000" ObjetoImp="01" /></cfdi:Conceptos><cfdi:Complemento><tfd:TimbreFiscalDigital xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/cfd/TimbreFiscalDigital/TimbreFiscalDigitalv11.xsd" FechaTimbrado="2026-09-01T19:30:26" NoCertificadoSAT="30001000000500003456" RfcProvCertif="SPR190613I52" SelloCFD="s24IV21tMl2+E6eeDSq9FEaNF8sA2AaPX3bmjafU76ItSVn8ojWP4c5+9uJIJ1y0q03K7GcBo53xQ/5cSmpP9x9LggAo6jQyMnNiMS9CJUQ4LXUajJMnUyzyIJiIrfZst+cfauBsxzL+nv1cnRmDp+47VHJ14oegYXKlF+avb3HhBz63dBjSHa0x1J84+v/e8h7HoO1zdOOwGjOuhXFn93Ok+rgBiFoZhuLMUGw5zphRsf0DtzqpG1TCwIGAp7YyAZTDN27+icgkl0NzJrRrhIqTzaMx2Q+rTdzSPTjLsYGEtKIdzDcD/DDdZ/TB/3ANXVr5/gFcYNebVi+oMSmS6w==" SelloSAT="QG0Bzz9PrmELg2w5bVc+hFOAn52CZzaV1kKjZhYUFEcOKMg9mSb34g9TGYqlYtvXmBJcKjL27Q8L4htXMCYP5Uya7alS9wWSiiZkrFyDxzkuHkydUPnCqU9g/RdCHG80lgXxt8Ov3lOLFZYZWme8GLlhcFa2Ns528dp+jTg2Rxz9SfmzIsHepoufgXcWvGFgb+D5OPOKxnOenN3TS26Om6l+tErghx0EzvdBZI5LKsjspDv7X8VQGIQ3OwWASp3KS/iyB3/nnxzcRrXk3Cumw2M8fsuvd1GA3MoZ1vzAWh0Wz58XcNfTVHdIISJfpIrggTB6V8VrtjKDqrX2XUcT/g==" UUID="b203381c-7cd4-4298-93ce-c6a4bd168bad" Version="1.1" xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" /></cfdi:Complemento></cfdi:Comprobante>
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><cfdi:Comprobante xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Moneda="MXN" TipoCambio="1" Total="2320.00" xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd" Exportacion="01" MetodoPago="PPD" TipoDeComprobante="I" SubTotal="2000.00" Sello="UHzBuYL6HzjxQtncPYnZI6OPwEMFSFwvdsO2c6gyjAtYTqCQKyCt3h24z3zEBFlfroDgvXVi7t9uON/Xa+0S518QhWjopkPwISueMQ6OW+sPunnH9Cs8fyk0kaFI56Q6EpK5HU5dEy9wGbeyAKNEkitT3ktLaVx0WB1WNUWM+EJlXmqvdi6GVHOfcbXiBM1LgkzS0S3T3u/+kFgqQyDYuNz5cvcXCzVHZ2m1s2MOEA05CazdazuL/5Y5hGJd2d0HbQMd2JPlCQwxeRbx7LvprD2+c8f3QQYdkOHZMiNUdfKijr/7kbr7cWpizRVAU1AU7jchjvZozCM7chsnahezag==" Certificado="MIIFsDCCA5igAwIBAgIUMzAwMDEwMDAwMDA1MDAwMDM0MTYwDQYJKoZIhvcNAQELBQAwggErMQ8wDQYDVQQDDAZBQyBVQVQxLjAsBgNVBAoMJVNFUlZJQ0lPIERFIEFETUlOSVNUUkFDSU9OIFRSSUJVVEFSSUExGjAYBgNVBAsMEVNBVC1JRVMgQXV0aG9yaXR5MSgwJgYJKoZIhvcNAQkBFhlvc2Nhci5tYXJ0aW5lekBzYXQuZ29iLm14MR0wGwYDVQQJDBQzcmEgY2VycmFkYSBkZSBjYWxpejEOMAwGA1UEEQwFMDYzNzAxCzAJBgNVBAYTAk1YMRkwFwYDVQQIDBBDSVVEQUQgREUgTUVYSUNPMREwDwYDVQQHDAhDT1lPQUNBTjERMA8GA1UELRMIMi41LjQuNDUxJTAjBgkqhkiG9w0BCQITFnJlc3BvbnNhYmxlOiBBQ0RNQS1TQVQwHhcNMjMwNTE4MTE0MzUxWhcNMjcwNTE4MTE0MzUxWjCB1zEnMCUGA1UEAxMeRVNDVUVMQSBLRU1QRVIgVVJHQVRFIFNBIERFIENWMScwJQYDVQQpEx5FU0NVRUxBIEtFTVBFUiBVUkdBVEUgU0EgREUgQ1YxJzAlBgNVBAoTHkVTQ1VFTEEgS0VNUEVSIFVSR0FURSBTQSBERSBDVjElMCMGA1UELRMcRUtVOTAwMzE3M0M5IC8gVkFEQTgwMDkyN0RKMzEeMBwGA1UEBRMVIC8gVkFEQTgwMDkyN0hTUlNSTDA1MRMwEQYDVQQLEwpTdWN1cnNhbCAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtmecO6n2GS0zL025gbHGQVxznPDICoXzR2uUngz4DqxVUC/w9cE6FxSiXm2ap8Gcjg7wmcZfm85EBaxCx/0J2u5CqnhzIoGCdhBPuhWQnIh5TLgj/X6uNquwZkKChbNe9aeFirU/JbyN7Egia9oKH9KZUsodiM/pWAH00PCtoKJ9OBcSHMq8Rqa3KKoBcfkg1ZrgueffwRLws9yOcRWLb02sDOPzGIm/jEFicVYt2Hw1qdRE5xmTZ7AGG0UHs+unkGjpCVeJ+BEBn0JPLWVvDKHZAQMj6s5Bku35+d/MyATkpOPsGT/VTnsouxekDfikJD1f7A1ZpJbqDpkJnss3vQIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQsFAAOCAgEAFaUgj5PqgvJigNMgtrdXZnbPfVBbukAbW4OGnUhNrA7SRAAfv2BSGk16PI0nBOr7qF2mItmBnjgEwk+DTv8Zr7w5qp7vleC6dIsZFNJoa6ZndrE/f7KO1CYruLXr5gwEkIyGfJ9NwyIagvHHMszzyHiSZIA850fWtbqtythpAliJ2jF35M5pNS+YTkRB+T6L/c6m00ymN3q9lT1rB03YywxrLreRSFZOSrbwWfg34EJbHfbFXpCSVYdJRfiVdvHnewN0r5fUlPtR9stQHyuqewzdkyb5jTTw02D2cUfL57vlPStBj7SEi3uOWvLrsiDnnCIxRMYJ2UA2ktDKHk+zWnsDmaeleSzonv2CHW42yXYPCvWi88oE1DJNYLNkIjua7MxAnkNZbScNw01A6zbLsZ3y8G6eEYnxSTRfwjd8EP4kdiHNJftm7Z4iRU7HOVh79/lRWB+gd171s3d/mI9kte3MRy6V8MMEMCAnMboGpaooYwgAmwclI2XZCczNWXfhaWe0ZS5PmytD/GDpXzkX0oEgY9K/uYo5V77NdZbGAjmyi8cE2B2ogvyaN2XfIInrZPgEffJ4AB7kFA2mwesdLOCh0BLD9itmCve3A1FGR4+stO2ANUoiI3w3Tv2yQSg4bjeDlJ08lXaaFCLW2peEXMXjQUk7fmpb5MNuOUTW6BE=" NoCertificado="30001000000500003416" FormaPago="99" LugarExpedicion="42501" Fecha="2026-09-01T20:08:03" Folio="2" Serie="TRA" Version="4.0" xmlns:cfdi="http://www.sat.gob.mx/cfd/4"><cfdi:Emisor Rfc="EKU9003173C9" Nombre="ESCUELA KEMPER URGATE" RegimenFiscal="601" /><cfdi:Receptor Rfc="EKU9003173C9" Nombre="ESCUELA KEMPER URGATE" DomicilioFiscalReceptor="42501" RegimenFiscalReceptor="601" UsoCFDI="G03" /><cfdi:Conceptos><cfdi:Concepto ClaveProdServ="83101500" NoIdentificacion="00001" Cantidad="1.0000" ClaveUnidad="MTQ" Unidad="NO APLICA" Descripcion="Pago adelantado de derechos y aportaciones" ValorUnitario="2000.00" Importe="2000.000000" ObjetoImp="02"><cfdi:Impuestos><cfdi:Traslados><cfdi:Traslado Base="2000.000000" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="320.00" /></cfdi:Traslados></cfdi:Impuestos></cfdi:Concepto></cfdi:Conceptos><cfdi:Impuestos TotalImpuestosTrasladados="320.00"><cfdi:Traslados><cfdi:Traslado Base="2000.00" Impuesto="002" TipoFactor="Tasa" TasaOCuota="0.160000" Importe="320.00" /></cfdi:Traslados></cfdi:Impuestos><cfdi:Complemento><tfd:TimbreFiscalDigital xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/cfd/TimbreFiscalDigital/TimbreFiscalDigitalv11.xsd" FechaTimbrado="2026-09-01T21:46:46" NoCertificadoSAT="30001000000500003456" RfcProvCertif="SPR190613I52" SelloCFD="UHzBuYL6HzjxQtncPYnZI6OPwEMFSFwvdsO2c6gyjAtYTqCQKyCt3h24z3zEBFlfroDgvXVi7t9uON/Xa+0S518QhWjopkPwISueMQ6OW+sPunnH9Cs8fyk0kaFI56Q6EpK5HU5dEy9wGbeyAKNEkitT3ktLaVx0WB1WNUWM+EJlXmqvdi6GVHOfcbXiBM1LgkzS0S3T3u/+kFgqQyDYuNz5cvcXCzVHZ2m1s2MOEA05CazdazuL/5Y5hGJd2d0HbQMd2JPlCQwxeRbx7LvprD2+c8f3QQYdkOHZMiNUdfKijr/7kbr7cWpizRVAU1AU7jchjvZozCM7chsnahezag==" SelloSAT="LD+t3J1eJ2Lldc/OYJv0kcHl0u/tLsqf4nLABwr/D6Mt/j5TPOpW3qnKsCZox1sMYzm9SCdaDqE3QWvRn5zSx+Wok5AOnmU3Ci+X3exJs3434jQOpqsQzf6YUX0V3S3JWOgpL4x9BlNueXNgY0tssH5tqOMxsIC73bK4OXemMJSeZGzzlerKZQBQuEYlONGPgB1CcDu6ps1w9aVRp3EB8nbOf6rJYWUHYD4N1qBswsyRXEGtYDuxpsXSDZ/wVntWlTbWtix1jJfn3SUsfpYURwayioVyZc/52C5Z3UA1pXCO+6JAin7Q8OjunuiHDaDr8zFX81UHgdc49yaP4mDsbQ==" UUID="d4d1a16b-3ae2-43e6-985a-7f01596b6050" Version="1.1" xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" /></cfdi:Complemento></cfdi:Comprobante>
|
||||
@@ -65,6 +65,10 @@
|
||||
HeaderText="Precio"
|
||||
DataFormatString="{0:N2}"
|
||||
ItemStyle-HorizontalAlign="Right" />
|
||||
<asp:BoundField DataField="ObjetoImpuesto"
|
||||
HeaderText="Objeto de impuesto" />
|
||||
<asp:BoundField DataField="TratamientoIVA"
|
||||
HeaderText="IVA" />
|
||||
<asp:CheckBoxField DataField="EsActivo" HeaderText="Activo" />
|
||||
<asp:TemplateField HeaderText="Acciones">
|
||||
<ItemTemplate>
|
||||
@@ -276,6 +280,34 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="tra-modal-field">
|
||||
<label for="<%= DdlObjetoImpuesto.ClientID %>">
|
||||
Objeto de impuesto *
|
||||
</label>
|
||||
<asp:DropDownList ID="DdlObjetoImpuesto"
|
||||
runat="server"
|
||||
CssClass="form-control input-sm select2me"
|
||||
DataTextField="ObjetoImpuesto"
|
||||
DataValueField="CveObjetoImpuesto" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="tra-modal-field">
|
||||
<label for="<%= DdlTratamientoIva.ClientID %>">
|
||||
Tratamiento de IVA *
|
||||
</label>
|
||||
<asp:DropDownList ID="DdlTratamientoIva"
|
||||
runat="server"
|
||||
CssClass="form-control input-sm select2me">
|
||||
<asp:ListItem Text="IVA general" Value="-1" />
|
||||
<asp:ListItem Text="Sin IVA" Value="0" />
|
||||
</asp:DropDownList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button"
|
||||
|
||||
@@ -126,6 +126,8 @@ namespace SIG.Web.Pages.Catalogos
|
||||
TxtDescripcion.Text = string.Empty;
|
||||
DdlTipo.SelectedValue = string.Empty;
|
||||
TxtPrecio.Text = "0.00";
|
||||
SeleccionarValor(DdlObjetoImpuesto, "2");
|
||||
SeleccionarValor(DdlTratamientoIva, "-1");
|
||||
ChkActivo.Checked = true;
|
||||
UpEdicion.Update();
|
||||
MostrarModal("ModalEdit");
|
||||
@@ -224,12 +226,22 @@ namespace SIG.Web.Pages.Catalogos
|
||||
int tipo;
|
||||
int clasificacion;
|
||||
int unidadMedida;
|
||||
byte cveObjetoImpuesto;
|
||||
decimal iva;
|
||||
|
||||
int.TryParse(DdlTipo.SelectedValue, out tipo);
|
||||
int.TryParse(DdlClasificacion.SelectedValue, out clasificacion);
|
||||
int.TryParse(
|
||||
DdlUnidadMedida.SelectedValue,
|
||||
out unidadMedida);
|
||||
byte.TryParse(
|
||||
DdlObjetoImpuesto.SelectedValue,
|
||||
out cveObjetoImpuesto);
|
||||
decimal.TryParse(
|
||||
DdlTratamientoIva.SelectedValue,
|
||||
NumberStyles.Number,
|
||||
CultureInfo.InvariantCulture,
|
||||
out iva);
|
||||
|
||||
var productoServicio = new ModeloProductoServicio
|
||||
{
|
||||
@@ -240,6 +252,8 @@ namespace SIG.Web.Pages.Catalogos
|
||||
CveClasificacion = clasificacion,
|
||||
CveUnidadMedida = unidadMedida,
|
||||
Precio = precio,
|
||||
CveObjetoImpuesto = cveObjetoImpuesto,
|
||||
IVA = iva,
|
||||
EsActivo = ChkActivo.Checked
|
||||
};
|
||||
|
||||
@@ -317,6 +331,16 @@ namespace SIG.Web.Pages.Catalogos
|
||||
DdlUnidadMedida,
|
||||
productoServicio.CveUnidadMedida.ToString(
|
||||
CultureInfo.InvariantCulture));
|
||||
SeleccionarValor(
|
||||
DdlObjetoImpuesto,
|
||||
productoServicio.CveObjetoImpuesto.ToString(
|
||||
CultureInfo.InvariantCulture));
|
||||
SeleccionarValor(
|
||||
DdlTratamientoIva,
|
||||
productoServicio.IVA.HasValue &&
|
||||
productoServicio.IVA.Value == 0m
|
||||
? "0"
|
||||
: "-1");
|
||||
TxtPrecio.Text = productoServicio.Precio.ToString(
|
||||
"0.00",
|
||||
CultureInfo.CurrentCulture);
|
||||
@@ -357,6 +381,12 @@ namespace SIG.Web.Pages.Catalogos
|
||||
0,
|
||||
new ListItem("Seleccione", string.Empty));
|
||||
|
||||
DdlObjetoImpuesto.DataSource = opciones.ObjetosImpuesto;
|
||||
DdlObjetoImpuesto.DataBind();
|
||||
DdlObjetoImpuesto.Items.Insert(
|
||||
0,
|
||||
new ListItem("Seleccione", string.Empty));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -471,8 +471,17 @@
|
||||
NullDisplayText="—" />
|
||||
<asp:BoundField DataField="Cantidad" HeaderText="Cantidad"
|
||||
DataFormatString="{0:N4}" />
|
||||
<asp:BoundField DataField="Precio" HeaderText="Precio"
|
||||
<asp:BoundField DataField="Importe" HeaderText="Importe vigente"
|
||||
DataFormatString="{0:C2}" HtmlEncode="false" />
|
||||
<asp:BoundField DataField="ObjetoImpuesto"
|
||||
HeaderText="Objeto de impuesto" />
|
||||
<asp:BoundField DataField="PorcentajeIVA"
|
||||
HeaderText="IVA"
|
||||
DataFormatString="{0:P2}" />
|
||||
<asp:BoundField DataField="ImporteIVA"
|
||||
HeaderText="Importe IVA"
|
||||
DataFormatString="{0:C2}"
|
||||
HtmlEncode="false" />
|
||||
<asp:BoundField DataField="Total" HeaderText="Total"
|
||||
DataFormatString="{0:C2}" HtmlEncode="false" />
|
||||
<asp:TemplateField HeaderText="Acciones">
|
||||
@@ -486,15 +495,6 @@
|
||||
ToolTip="Editar concepto">
|
||||
<i class="fa fa-pencil"></i>
|
||||
</asp:LinkButton>
|
||||
<asp:LinkButton ID="BtnEditGlobalPrice"
|
||||
runat="server"
|
||||
CssClass="btn btn-circle btn-xs yellow"
|
||||
CommandName="EditarPrecioGlobal"
|
||||
CommandArgument='<%# Eval("CveTramitePagoDetalle") %>'
|
||||
CausesValidation="false"
|
||||
ToolTip="Editar precio global del producto o servicio">
|
||||
<i class="fa fa-dollar"></i>
|
||||
</asp:LinkButton>
|
||||
<asp:LinkButton ID="BtnDeletePaymentDetail"
|
||||
runat="server"
|
||||
CssClass="btn btn-circle btn-xs red"
|
||||
@@ -806,6 +806,49 @@
|
||||
Use una cantidad mayor que cero; se permiten hasta cuatro decimales.
|
||||
</span>
|
||||
</div>
|
||||
<div class="tra-modal-field">
|
||||
<label>Importe antes de IVA *</label>
|
||||
<asp:TextBox ID="TxtPaymentDetailAmount"
|
||||
runat="server"
|
||||
CssClass="form-control"
|
||||
MaxLength="20" />
|
||||
<span class="help-block">
|
||||
Al seleccionar el producto se propone su precio unitario actual.
|
||||
Los cambios posteriores generan una nueva vigencia para el trámite.
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-7">
|
||||
<div class="tra-modal-field">
|
||||
<label for="<%= DdlObjetoImpuestoDetallePago.ClientID %>">
|
||||
Objeto de impuesto *
|
||||
</label>
|
||||
<asp:DropDownList ID="DdlObjetoImpuestoDetallePago"
|
||||
runat="server"
|
||||
CssClass="form-control select2me"
|
||||
Width="100%">
|
||||
<asp:ListItem Text="Seleccione" Value="" />
|
||||
<asp:ListItem Text="01 - No objeto de impuesto" Value="1" />
|
||||
<asp:ListItem Text="02 - Sí objeto de impuesto" Value="2" />
|
||||
<asp:ListItem Text="03 - Sí objeto y no obligado al desglose" Value="3" />
|
||||
</asp:DropDownList>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
<div class="tra-modal-field">
|
||||
<label for="<%= TxtPorcentajeIvaDetallePago.ClientID %>">
|
||||
IVA (%) *
|
||||
</label>
|
||||
<asp:TextBox ID="TxtPorcentajeIvaDetallePago"
|
||||
runat="server"
|
||||
CssClass="form-control"
|
||||
MaxLength="10" />
|
||||
<span class="help-block">
|
||||
Capture 16 para una tasa del 16%.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn default" data-dismiss="modal">Cancelar</button>
|
||||
@@ -827,60 +870,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ModalGlobalPrice" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<asp:UpdatePanel ID="UpGlobalPriceModal" runat="server"
|
||||
UpdateMode="Conditional" ChildrenAsTriggers="false">
|
||||
<ContentTemplate>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Actualizar precio global</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-warning tra-global-price-warning">
|
||||
<i class="fa fa-warning"></i>
|
||||
<div>
|
||||
<strong>Este cambio es global.</strong>
|
||||
<p>
|
||||
El nuevo precio modificará directamente el producto o servicio y
|
||||
afectará todos los módulos que lo utilicen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tra-modal-field">
|
||||
<label>Producto o servicio</label>
|
||||
<p class="form-control-static">
|
||||
<asp:Literal ID="LitGlobalPriceProduct" runat="server" />
|
||||
</p>
|
||||
</div>
|
||||
<div class="tra-modal-field">
|
||||
<label>Nuevo precio *</label>
|
||||
<asp:TextBox ID="TxtGlobalPrice"
|
||||
runat="server"
|
||||
CssClass="form-control"
|
||||
MaxLength="20" />
|
||||
</div>
|
||||
<asp:CheckBox ID="ChkConfirmGlobalPrice"
|
||||
runat="server"
|
||||
Text=" Confirmo que este precio cambiará a nivel global" />
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn default" data-dismiss="modal">Cancelar</button>
|
||||
<asp:Button ID="BtnSaveGlobalPrice"
|
||||
runat="server"
|
||||
CssClass="btn yellow"
|
||||
Text="Actualizar precio global"
|
||||
OnClick="BtnSaveGlobalPrice_Click" />
|
||||
</div>
|
||||
</div>
|
||||
</ContentTemplate>
|
||||
<Triggers>
|
||||
<asp:AsyncPostBackTrigger ControlID="BtnSaveGlobalPrice" EventName="Click" />
|
||||
</Triggers>
|
||||
</asp:UpdatePanel>
|
||||
</div>
|
||||
</div>
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ID="ContentScripts" ContentPlaceHolderID="J" runat="server">
|
||||
|
||||
@@ -65,12 +65,6 @@ namespace SIG.Web.Pages.Catalogos
|
||||
set { ViewState["CveTramitePagoDetalleActual"] = value; }
|
||||
}
|
||||
|
||||
private int CveProductoPrecioActual
|
||||
{
|
||||
get { return ViewState["CveProductoPrecioActual"] as int? ?? 0; }
|
||||
set { ViewState["CveProductoPrecioActual"] = value; }
|
||||
}
|
||||
|
||||
private List<ModeloProductoServicioTramite>
|
||||
ProductosServiciosDisponibles
|
||||
{
|
||||
@@ -700,6 +694,9 @@ namespace SIG.Web.Pages.Catalogos
|
||||
DdlProductService.SelectedIndex = 0;
|
||||
DdlUnidadMedidaDetallePago.SelectedIndex = 0;
|
||||
TxtPaymentDetailQuantity.Text = "1";
|
||||
TxtPaymentDetailAmount.Text = string.Empty;
|
||||
DdlObjetoImpuestoDetallePago.SelectedIndex = 0;
|
||||
TxtPorcentajeIvaDetallePago.Text = "16.00";
|
||||
UpPaymentDetailModal.Update();
|
||||
Show("ModalPaymentDetail");
|
||||
}
|
||||
@@ -719,10 +716,6 @@ namespace SIG.Web.Pages.Catalogos
|
||||
{
|
||||
EditPaymentDetail(id);
|
||||
}
|
||||
else if (e.CommandName == "EditarPrecioGlobal")
|
||||
{
|
||||
EditGlobalPrice(id);
|
||||
}
|
||||
else if (e.CommandName == "EliminarDetalle")
|
||||
{
|
||||
DeletePaymentDetail(id);
|
||||
@@ -735,6 +728,9 @@ namespace SIG.Web.Pages.Catalogos
|
||||
int cveProductoServicio;
|
||||
int cveUnidadMedida;
|
||||
decimal cantidad;
|
||||
decimal importe;
|
||||
byte cveObjetoImpuesto;
|
||||
decimal porcentajeIvaCapturado;
|
||||
if (!int.TryParse(
|
||||
DdlProductService.SelectedValue,
|
||||
out cveProductoServicio) ||
|
||||
@@ -746,10 +742,23 @@ namespace SIG.Web.Pages.Catalogos
|
||||
!TryParseDecimal(
|
||||
TxtPaymentDetailQuantity.Text,
|
||||
out cantidad) ||
|
||||
cantidad <= 0)
|
||||
cantidad <= 0 ||
|
||||
!TryParseDecimal(
|
||||
TxtPaymentDetailAmount.Text,
|
||||
out importe) ||
|
||||
importe < 0 ||
|
||||
!byte.TryParse(
|
||||
DdlObjetoImpuestoDetallePago.SelectedValue,
|
||||
out cveObjetoImpuesto) ||
|
||||
cveObjetoImpuesto <= 0 ||
|
||||
!TryParseDecimal(
|
||||
TxtPorcentajeIvaDetallePago.Text,
|
||||
out porcentajeIvaCapturado) ||
|
||||
porcentajeIvaCapturado < 0 ||
|
||||
porcentajeIvaCapturado > 100)
|
||||
{
|
||||
Alert(
|
||||
"Seleccione el producto o servicio, la unidad de medida y capture una cantidad mayor que cero.",
|
||||
"Seleccione el producto o servicio, la unidad de medida y el objeto de impuesto; capture una cantidad, un importe y un IVA válidos.",
|
||||
TipoMensaje.MsgAdvertencia);
|
||||
Show("ModalPaymentDetail");
|
||||
return;
|
||||
@@ -761,7 +770,15 @@ namespace SIG.Web.Pages.Catalogos
|
||||
CveTramitePago = CveTramitePagoSeleccionado,
|
||||
CvePS = cveProductoServicio,
|
||||
CveUM = cveUnidadMedida,
|
||||
Cantidad = decimal.Round(cantidad, 4)
|
||||
Cantidad = decimal.Round(cantidad, 4),
|
||||
Importe = decimal.Round(importe, 2),
|
||||
CveObjetoImpuesto = cveObjetoImpuesto,
|
||||
PorcentajeIVA = cveObjetoImpuesto == 1
|
||||
? 0m
|
||||
: decimal.Round(
|
||||
porcentajeIvaCapturado / 100m,
|
||||
6),
|
||||
FechaInicioVigencia = DateTime.Today
|
||||
};
|
||||
|
||||
DbResult<int> result =
|
||||
@@ -799,6 +816,9 @@ namespace SIG.Web.Pages.Catalogos
|
||||
cveProductoServicio <= 0)
|
||||
{
|
||||
DdlUnidadMedidaDetallePago.SelectedIndex = 0;
|
||||
TxtPaymentDetailAmount.Text = string.Empty;
|
||||
DdlObjetoImpuestoDetallePago.SelectedIndex = 0;
|
||||
TxtPorcentajeIvaDetallePago.Text = "16.00";
|
||||
UpPaymentDetailModal.Update();
|
||||
Show("ModalPaymentDetail");
|
||||
return;
|
||||
@@ -813,6 +833,9 @@ namespace SIG.Web.Pages.Catalogos
|
||||
productoServicio.CveUnidadMedida <= 0)
|
||||
{
|
||||
DdlUnidadMedidaDetallePago.SelectedIndex = 0;
|
||||
TxtPaymentDetailAmount.Text = string.Empty;
|
||||
DdlObjetoImpuestoDetallePago.SelectedIndex = 0;
|
||||
TxtPorcentajeIvaDetallePago.Text = "16.00";
|
||||
UpPaymentDetailModal.Update();
|
||||
Show("ModalPaymentDetail");
|
||||
return;
|
||||
@@ -821,58 +844,22 @@ namespace SIG.Web.Pages.Catalogos
|
||||
SelectDropDownValue(
|
||||
DdlUnidadMedidaDetallePago,
|
||||
productoServicio.CveUnidadMedida);
|
||||
TxtPaymentDetailAmount.Text =
|
||||
productoServicio.Precio.ToString(
|
||||
"0.00",
|
||||
CultureInfo.InvariantCulture);
|
||||
SelectDropDownValue(
|
||||
DdlObjetoImpuestoDetallePago,
|
||||
productoServicio.CveObjetoImpuesto);
|
||||
TxtPorcentajeIvaDetallePago.Text =
|
||||
(productoServicio.PorcentajeIVA * 100m).ToString(
|
||||
"0.####",
|
||||
CultureInfo.InvariantCulture);
|
||||
|
||||
UpPaymentDetailModal.Update();
|
||||
Show("ModalPaymentDetail");
|
||||
}
|
||||
|
||||
protected void BtnSaveGlobalPrice_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetActiveTab(2);
|
||||
decimal price;
|
||||
if (!ChkConfirmGlobalPrice.Checked)
|
||||
{
|
||||
Alert(
|
||||
"Confirme que comprende que el precio cambiará a nivel global.",
|
||||
TipoMensaje.MsgAdvertencia);
|
||||
Show("ModalGlobalPrice");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryParseDecimal(TxtGlobalPrice.Text, out price) ||
|
||||
price < 0)
|
||||
{
|
||||
Alert(
|
||||
"Capture un precio válido mayor o igual que cero.",
|
||||
TipoMensaje.MsgAdvertencia);
|
||||
Show("ModalGlobalPrice");
|
||||
return;
|
||||
}
|
||||
|
||||
DbResult<int> result =
|
||||
AppServices.TramiteCatalogService.UpdateProductoServicioPrecio(
|
||||
CveProductoPrecioActual,
|
||||
decimal.Round(price, 2),
|
||||
CurrentUser.CveUsuario,
|
||||
CurrentUser.NombreDominio);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
Alert(result.UserMessage, TipoMensaje.MsgAdvertencia);
|
||||
Show("ModalGlobalPrice");
|
||||
return;
|
||||
}
|
||||
|
||||
BindProducts();
|
||||
BindPayments();
|
||||
BindPaymentDetails();
|
||||
UpTabs.Update();
|
||||
Hide("ModalGlobalPrice");
|
||||
Alert(
|
||||
"Precio global actualizado correctamente.",
|
||||
TipoMensaje.ToastExito);
|
||||
}
|
||||
|
||||
private void LoadProcedure()
|
||||
{
|
||||
DbResult<TipoTramiteModel> result =
|
||||
@@ -1426,6 +1413,17 @@ namespace SIG.Web.Pages.Catalogos
|
||||
result.Data.Cantidad.ToString(
|
||||
"0.####",
|
||||
CultureInfo.InvariantCulture);
|
||||
TxtPaymentDetailAmount.Text =
|
||||
result.Data.Importe.ToString(
|
||||
"0.00",
|
||||
CultureInfo.InvariantCulture);
|
||||
SelectDropDownValue(
|
||||
DdlObjetoImpuestoDetallePago,
|
||||
result.Data.CveObjetoImpuesto);
|
||||
TxtPorcentajeIvaDetallePago.Text =
|
||||
(result.Data.PorcentajeIVA * 100m).ToString(
|
||||
"0.####",
|
||||
CultureInfo.InvariantCulture);
|
||||
BindPaymentDetails();
|
||||
UpPaymentDetailModal.Update();
|
||||
Show("ModalPaymentDetail");
|
||||
@@ -1453,48 +1451,6 @@ namespace SIG.Web.Pages.Catalogos
|
||||
TipoMensaje.ToastExito);
|
||||
}
|
||||
|
||||
private void EditGlobalPrice(int paymentDetailId)
|
||||
{
|
||||
DbResult<TramitePagoDetalleModel> detailResult =
|
||||
AppServices.TramiteCatalogService.GetPagoDetalle(
|
||||
paymentDetailId,
|
||||
CurrentUser.CveUsuario,
|
||||
CurrentUser.NombreDominio);
|
||||
|
||||
if (!detailResult.Success || detailResult.Data == null)
|
||||
{
|
||||
Alert(
|
||||
detailResult.UserMessage,
|
||||
TipoMensaje.MsgAdvertencia);
|
||||
return;
|
||||
}
|
||||
|
||||
DbResult<ModeloProductoServicioTramite> productResult =
|
||||
AppServices.TramiteCatalogService.GetProductoServicio(
|
||||
detailResult.Data.CvePS,
|
||||
CurrentUser.CveUsuario,
|
||||
CurrentUser.NombreDominio);
|
||||
|
||||
if (!productResult.Success || productResult.Data == null)
|
||||
{
|
||||
Alert(
|
||||
productResult.UserMessage,
|
||||
TipoMensaje.MsgAdvertencia);
|
||||
return;
|
||||
}
|
||||
|
||||
CveProductoPrecioActual = productResult.Data.CvePS;
|
||||
LitGlobalPriceProduct.Text =
|
||||
Server.HtmlEncode(productResult.Data.ProductoDisplay);
|
||||
TxtGlobalPrice.Text =
|
||||
productResult.Data.Precio.ToString(
|
||||
"0.00",
|
||||
CultureInfo.InvariantCulture);
|
||||
ChkConfirmGlobalPrice.Checked = false;
|
||||
UpGlobalPriceModal.Update();
|
||||
Show("ModalGlobalPrice");
|
||||
}
|
||||
|
||||
private void ClearOptionsPanel()
|
||||
{
|
||||
CvePreguntaOpcionesSeleccionada = 0;
|
||||
|
||||
@@ -648,16 +648,14 @@ namespace SIG.Web.Pages.Ventas
|
||||
GvConceptos.DataBind();
|
||||
|
||||
decimal subtotal = conceptos.Sum(
|
||||
concepto =>
|
||||
Math.Round(
|
||||
concepto.Cantidad * concepto.PrecioUnitario,
|
||||
2));
|
||||
concepto => concepto.Importe);
|
||||
decimal descuento = conceptos.Sum(
|
||||
concepto => concepto.Descuento);
|
||||
decimal iva = conceptos.Sum(
|
||||
concepto => concepto.IVA);
|
||||
decimal total = conceptos.Sum(
|
||||
concepto => concepto.Importe);
|
||||
decimal total = Math.Round(
|
||||
subtotal - descuento + iva,
|
||||
2);
|
||||
|
||||
TotalVentaActual = total;
|
||||
|
||||
@@ -689,6 +687,16 @@ namespace SIG.Web.Pages.Ventas
|
||||
venta.VentaGenerada &&
|
||||
!venta.VentaTimbrada &&
|
||||
TienePermiso(PermisoTimbrar);
|
||||
LnkDescargarXmlSinTimbrar.Visible =
|
||||
venta.CveCfdiDocumento.HasValue &&
|
||||
venta.CveCfdiDocumento.Value > 0;
|
||||
LnkDescargarXmlSinTimbrar.NavigateUrl =
|
||||
LnkDescargarXmlSinTimbrar.Visible
|
||||
? ResolveUrl(
|
||||
"~/DescargaXmlCfdi.ashx?documento=" +
|
||||
venta.CveCfdiDocumento.Value.ToString(
|
||||
CultureInfo.InvariantCulture))
|
||||
: string.Empty;
|
||||
PnlCancelarTimbre.Visible =
|
||||
venta.VentaTimbrada &&
|
||||
TienePermiso(PermisoCancelarTimbre);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<add key="SmtpPassword" value="nzwt zrnc zcvq ztpx" />
|
||||
<add key="EmailFrom" value="notificaciones@sig.adssistemas.mx" />
|
||||
<add key="EmailFromDisplayName" value="Agua de Hermosillo" />
|
||||
<add key="CredencialPacProfactPruebas" value="mvpNUXmQfK8=" />
|
||||
<!-- reCAPTCHA v2: al desactivarlo no se muestra ni se valida. La clave secreta nunca se envía al navegador. -->
|
||||
<add key="RecaptchaEnabled" value="true" />
|
||||
<add key="RecaptchaSiteKey" value="6LeVOFQtAAAAAOxZKnBiKFlnMnd90aR1PwJmUGgJ" />
|
||||
@@ -79,6 +80,7 @@
|
||||
<handlers>
|
||||
<add name="PdfViewerHandler" path="SigPdfViewerHandler.ashx" verb="*" type="SIG.Web.AppCode.SigControls.PDFViewer.PdfViewerHandler" resourceType="Unspecified" />
|
||||
<add name="PdfViewerUploadHandler" path="SigPdfViewerUploadHandler.ashx" verb="POST" type="SIG.Web.AppCode.SigControls.PDFViewer.PdfViewerUploadHandler" resourceType="Unspecified" />
|
||||
<add name="DescargaXmlCfdi" path="DescargaXmlCfdi.ashx" verb="GET" type="SIG.Web.Pages.Facturacion.DescargaXmlCfdi" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<defaultDocument enabled="true">
|
||||
<files>
|
||||
|
||||
86
Ventas_Prueba_Limpieza_20260901.sql
Normal file
86
Ventas_Prueba_Limpieza_20260901.sql
Normal file
@@ -0,0 +1,86 @@
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TABLE #VentasPrueba
|
||||
(
|
||||
CveVenta int NOT NULL PRIMARY KEY
|
||||
);
|
||||
|
||||
INSERT INTO #VentasPrueba
|
||||
(
|
||||
CveVenta
|
||||
)
|
||||
SELECT DISTINCT
|
||||
VD.CveVenta
|
||||
FROM dbo.VentasDetalle AS VD
|
||||
WHERE VD.CveSolicitud IS NOT NULL
|
||||
OR VD.CveCostoTramite IS NOT NULL
|
||||
OR VD.EsFondoInicial = 1;
|
||||
|
||||
SELECT
|
||||
V.CveVenta,
|
||||
V.Serie,
|
||||
V.Folio,
|
||||
V.Fecha,
|
||||
V.SubTotal,
|
||||
V.Descuento,
|
||||
V.IVA,
|
||||
V.Total
|
||||
FROM dbo.Ventas AS V
|
||||
INNER JOIN #VentasPrueba AS VP
|
||||
ON VP.CveVenta = V.CveVenta
|
||||
ORDER BY V.CveVenta;
|
||||
|
||||
IF EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.Vta_Pagos AS P
|
||||
INNER JOIN #VentasPrueba AS VP
|
||||
ON VP.CveVenta = P.CveVenta
|
||||
)
|
||||
BEGIN
|
||||
THROW 50002, 'La selección incluye ventas con pagos; la limpieza de prueba se canceló.', 1;
|
||||
END;
|
||||
|
||||
IF EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM dbo.Fac_CfdiDocumentos AS D
|
||||
INNER JOIN #VentasPrueba AS VP
|
||||
ON VP.CveVenta = D.CveOrigen
|
||||
WHERE D.TipoOrigen = 'VENTA'
|
||||
)
|
||||
BEGIN
|
||||
THROW 50003, 'La selección incluye ventas con documentos CFDI; la limpieza de prueba se canceló.', 1;
|
||||
END;
|
||||
|
||||
DELETE VDI
|
||||
FROM dbo.VentasDetalleImpuestos AS VDI
|
||||
INNER JOIN dbo.VentasDetalle AS VD
|
||||
ON VD.CveVentaDetalle = VDI.CveVentaDetalle
|
||||
INNER JOIN #VentasPrueba AS VP
|
||||
ON VP.CveVenta = VD.CveVenta;
|
||||
|
||||
DELETE VD
|
||||
FROM dbo.VentasDetalle AS VD
|
||||
INNER JOIN #VentasPrueba AS VP
|
||||
ON VP.CveVenta = VD.CveVenta;
|
||||
|
||||
DELETE SP
|
||||
FROM dbo.Tra_SolicitudesPagos AS SP
|
||||
INNER JOIN #VentasPrueba AS VP
|
||||
ON VP.CveVenta = SP.CveVenta;
|
||||
|
||||
DELETE V
|
||||
FROM dbo.Ventas AS V
|
||||
INNER JOIN #VentasPrueba AS VP
|
||||
ON VP.CveVenta = V.CveVenta;
|
||||
|
||||
SELECT
|
||||
@@ROWCOUNT AS VentasQueSeEliminarian;
|
||||
|
||||
ROLLBACK TRANSACTION;
|
||||
|
||||
-- Cambiar únicamente a COMMIT TRANSACTION después de revisar la selección.
|
||||
Reference in New Issue
Block a user